mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Add fatal_require and improved FatalError reporting interfaces
This commit is contained in:
@@ -110,6 +110,17 @@
|
|||||||
#define BEAST_BOOST_IS_AVAILABLE 1
|
#define BEAST_BOOST_IS_AVAILABLE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Config: BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||||
|
Turns off the debugging display of the beast version number
|
||||||
|
*/
|
||||||
|
#ifndef BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||||
|
#define BEAST_DISABLE_BEAST_VERSION_PRINTING 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Bind source configuration.
|
/** Bind source configuration.
|
||||||
|
|
||||||
Set one of these to manually force a particular implementation of bind().
|
Set one of these to manually force a particular implementation of bind().
|
||||||
|
|||||||
@@ -103,7 +103,6 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Config: BEAST_BOOST_IS_AVAILABLE
|
/** Config: BEAST_BOOST_IS_AVAILABLE
|
||||||
|
|
||||||
This activates boost specific features and improvements.
|
This activates boost specific features and improvements.
|
||||||
*/
|
*/
|
||||||
#ifndef BEAST_BOOST_IS_AVAILABLE
|
#ifndef BEAST_BOOST_IS_AVAILABLE
|
||||||
@@ -112,6 +111,15 @@
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Config: BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||||
|
Turns off the debugging display of the beast version number
|
||||||
|
*/
|
||||||
|
#ifndef BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||||
|
//#define BEAST_DISABLE_BEAST_VERSION_PRINTING 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Bind source configuration.
|
/** Bind source configuration.
|
||||||
|
|
||||||
Set one of these to manually force a particular implementation of bind().
|
Set one of these to manually force a particular implementation of bind().
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
BEAST TODO
|
BEAST TODO
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
- Use SemanticVersion for beast version numbers to replace BEAST_VERSION
|
||||||
|
|
||||||
|
- add support for a __PRETTY_FUNCTION__ equivalent for all environments
|
||||||
|
|
||||||
- add expectThrow() to UnitTest, where it expects an exception
|
- add expectThrow() to UnitTest, where it expects an exception
|
||||||
|
|
||||||
- Import secp256k1 from sipa
|
- Import secp256k1 from sipa
|
||||||
|
|||||||
@@ -17,6 +17,56 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
//
|
||||||
|
// FatalError::Reporter
|
||||||
|
//
|
||||||
|
|
||||||
|
void FatalError::Reporter::onFatalError (
|
||||||
|
char const* message, char const* stackBacktrace, char const* filePath, int lineNumber)
|
||||||
|
{
|
||||||
|
String formattedMessage = formatMessage (
|
||||||
|
message, stackBacktrace, filePath, lineNumber);
|
||||||
|
|
||||||
|
reportMessage (formattedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FatalError::Reporter::reportMessage (String& formattedMessage)
|
||||||
|
{
|
||||||
|
std::cerr << formattedMessage.toRawUTF8 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
String FatalError::Reporter::formatMessage (
|
||||||
|
char const* message, char const* stackBacktrace, char const* filePath, int lineNumber)
|
||||||
|
{
|
||||||
|
String formattedMessage;
|
||||||
|
formattedMessage.preallocateBytes (16 * 1024);
|
||||||
|
|
||||||
|
formattedMessage << message;
|
||||||
|
|
||||||
|
if (filePath != nullptr && filePath [0] != 0)
|
||||||
|
{
|
||||||
|
formattedMessage << ", in " << formatFilePath (filePath)
|
||||||
|
<< " line " << String (lineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
formattedMessage << newLine;
|
||||||
|
|
||||||
|
if (stackBacktrace != nullptr && stackBacktrace [0] != 0)
|
||||||
|
{
|
||||||
|
formattedMessage << "Stack:" << newLine;
|
||||||
|
formattedMessage << stackBacktrace;
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
String FatalError::Reporter::formatFilePath (char const* filePath)
|
||||||
|
{
|
||||||
|
return File::createFileWithoutCheckingPath (filePath).getFileName ();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
Static::Storage <Atomic <FatalError::Reporter*>, FatalError> FatalError::s_reporter;
|
Static::Storage <Atomic <FatalError::Reporter*>, FatalError> FatalError::s_reporter;
|
||||||
|
|
||||||
void FatalError::setReporter (Reporter& reporter)
|
void FatalError::setReporter (Reporter& reporter)
|
||||||
@@ -66,47 +116,14 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestReporter
|
|
||||||
: public FatalError::Reporter
|
|
||||||
, public Uncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit TestReporter (UnitTest& test)
|
|
||||||
: m_test (test)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void onFatalError (char const* message,
|
|
||||||
char const* stackBacktrace,
|
|
||||||
char const* fileName,
|
|
||||||
int lineNumber)
|
|
||||||
{
|
|
||||||
String s;
|
|
||||||
|
|
||||||
s << "Message = '" << message << "'" << newLine;
|
|
||||||
s << "File = '" << fileName << "' Line " << String (lineNumber) << newLine;
|
|
||||||
s << "Stack Trace:" << newLine;
|
|
||||||
s << stackBacktrace;
|
|
||||||
|
|
||||||
m_test.logMessage (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
UnitTest& m_test;
|
|
||||||
};
|
|
||||||
|
|
||||||
void runTest ()
|
void runTest ()
|
||||||
{
|
{
|
||||||
beginTestCase ("raise");
|
beginTestCase ("raise");
|
||||||
|
|
||||||
TestReporter reporter (*this);
|
|
||||||
|
|
||||||
FatalError::setReporter (reporter);
|
|
||||||
|
|
||||||
// We don't really expect the program to run after this
|
// We don't really expect the program to run after this
|
||||||
// but the unit test is here so you can manually test it.
|
// but the unit test is here so you can manually test it.
|
||||||
|
int shouldBeZero (1);
|
||||||
FatalError ("unit test", __FILE__, __LINE__);
|
fatal_require (shouldBeZero == 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,35 +36,93 @@ class FatalError : Uncopyable
|
|||||||
public:
|
public:
|
||||||
struct Reporter
|
struct Reporter
|
||||||
{
|
{
|
||||||
|
virtual ~Reporter () { }
|
||||||
|
|
||||||
/** Called when a fatal error is raised.
|
/** Called when a fatal error is raised.
|
||||||
|
|
||||||
Because the program is likely in an inconsistent state, it is a
|
Because the program is likely in an inconsistent state, it is a
|
||||||
good idea to do as little as possible from within this function.
|
good idea to do as little as possible from within this function.
|
||||||
It will be called from the thread that raised the fatal error.
|
It will be called from the thread that raised the fatal error.
|
||||||
|
|
||||||
|
The default implementation of this function first calls
|
||||||
|
formatMessage to produce the string, then calls reportMessage
|
||||||
|
to report the results.
|
||||||
|
|
||||||
|
You can override this to perform custom formatting.
|
||||||
|
|
||||||
|
@note filePath may be a zero length string if identifying
|
||||||
|
information was stripped from the executable for security.
|
||||||
|
|
||||||
|
@note stackBacktrace will be a string with zero characters for
|
||||||
|
platforms for which which don't support stack crawls, or
|
||||||
|
when symbolic information is missing from the executable.
|
||||||
|
|
||||||
@param message The error message.
|
@param message The error message.
|
||||||
@param stackBackTrace The stack of the thread that raised the error.
|
@param stackBackTrace The stack of the thread that raised the error.
|
||||||
@param fileName The source file that raised the error.
|
@param filePath A full or partial path to the source file that raised the error.
|
||||||
@param lineNumber The line number in the source file.
|
@param lineNumber The line number in the source file.
|
||||||
*/
|
*/
|
||||||
virtual void onFatalError (char const* message,
|
virtual void onFatalError (char const* message,
|
||||||
char const* stackBacktrace,
|
char const* stackBacktrace,
|
||||||
char const* fileName,
|
char const* filePath,
|
||||||
int lineNumber) = 0;
|
int lineNumber);
|
||||||
|
|
||||||
|
/** Called to report the message.
|
||||||
|
|
||||||
|
The default implementation simply writes this to standard error.
|
||||||
|
You can override this to perform additional things like logging
|
||||||
|
to a file or sending the message to another process.
|
||||||
|
|
||||||
|
@param formattedMessage The message to report.
|
||||||
|
*/
|
||||||
|
virtual void reportMessage (String& formattedMessage);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** Called to format the message.
|
||||||
|
|
||||||
|
The default implementation calls formatFilePath to produce
|
||||||
|
a formatted file name, and then creates a suitable string
|
||||||
|
containing all of the information.
|
||||||
|
|
||||||
|
You can override this function to format your own messages.
|
||||||
|
|
||||||
|
@param message The message from the report.
|
||||||
|
@param stackBacktrace The stack backtrace from the report.
|
||||||
|
@param filePath The file path from the report.
|
||||||
|
@param lineNumber The line number from the report
|
||||||
|
*/
|
||||||
|
virtual String formatMessage (char const* message,
|
||||||
|
char const* stackBacktrace,
|
||||||
|
char const* filePath,
|
||||||
|
int lineNumber);
|
||||||
|
|
||||||
|
/** Call to reformat the file path.
|
||||||
|
|
||||||
|
Usually the file is a full path, which we really don't care
|
||||||
|
to see and can also be a security hole.
|
||||||
|
|
||||||
|
The default implementation removes most of the useless
|
||||||
|
directory components from the front.
|
||||||
|
|
||||||
|
You can override this to do a custom format on the file path.
|
||||||
|
*/
|
||||||
|
virtual String formatFilePath (char const* filePath);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Set the fatal error reporter.
|
/** Set the fatal error reporter.
|
||||||
|
|
||||||
Note that if a fatal error is raised during the construction of
|
Note that if a fatal error is raised during the construction of
|
||||||
objects with static storage duration, it might not be possible to
|
objects with static storage duration, it might not be possible to
|
||||||
set the reporter before the error is raised.
|
set the reporter before the error is raised. The solution is not
|
||||||
|
to use objects with static storage duration that have non-trivial
|
||||||
|
constructors, use SharedSingleton instead.
|
||||||
|
|
||||||
The solution is not to use objects with static storage duration
|
The default behavior when no reporter is set is to invoke
|
||||||
that have non-trivial constructors, use SharedSingleton instead.
|
the base class version of Reporter::onFatalError.
|
||||||
|
|
||||||
If a reporter was previously set, this routine will do nothing.
|
If a reporter was previously set, this routine will do nothing.
|
||||||
|
|
||||||
@see SharedSingleton
|
@see SharedSingleton, Reporter
|
||||||
*/
|
*/
|
||||||
static void setReporter (Reporter& reporter);
|
static void setReporter (Reporter& reporter);
|
||||||
|
|
||||||
@@ -81,13 +139,24 @@ public:
|
|||||||
other threads will be blocked before the process terminates.
|
other threads will be blocked before the process terminates.
|
||||||
|
|
||||||
@param message A null terminated string, which should come from a constant.
|
@param message A null terminated string, which should come from a constant.
|
||||||
@param fileName Pass __FILE__ here.
|
@param filePath Pass __FILE__ here.
|
||||||
@param lineNumber Pass __LINE__ here.
|
@param lineNumber Pass __LINE__ here.
|
||||||
*/
|
*/
|
||||||
FatalError (char const* message, char const* fileName, int lineNumber);
|
FatalError (char const* message, char const* filePath, int lineNumber);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Static::Storage <Atomic <Reporter*>, FatalError> s_reporter;
|
static Static::Storage <Atomic <Reporter*>, FatalError> s_reporter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Fatal assertion macro.
|
||||||
|
These get compiled into the code regardless of the BEAST_DEBUG
|
||||||
|
setting, and call FatalError.
|
||||||
|
@see FatalError
|
||||||
|
*/
|
||||||
|
#define fatal_require_report(expression) \
|
||||||
|
{ if (beast::beast_isRunningUnderDebugger()) beast_breakDebugger; \
|
||||||
|
FatalError ("Assertion '" BEAST_STRINGIFY(expression) "' failed", __FILE__, __LINE__); \
|
||||||
|
BEAST_ANALYZER_NORETURN }
|
||||||
|
#define fatal_require(condition) { if (! (condition)) { fatal_require_report(condition); } }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifdef TWICE
|
||||||
|
#error die
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TWICE
|
||||||
|
|
||||||
FatalErrorReporter::FatalErrorReporter ()
|
FatalErrorReporter::FatalErrorReporter ()
|
||||||
{
|
{
|
||||||
FatalError::setReporter (*this);
|
FatalError::setReporter (*this);
|
||||||
@@ -14,20 +20,9 @@ FatalErrorReporter::~FatalErrorReporter ()
|
|||||||
FatalError::resetReporter (*this);
|
FatalError::resetReporter (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FatalErrorReporter::onFatalError (
|
void FatalErrorReporter::reportMessage (String& formattedMessage)
|
||||||
char const* message,
|
|
||||||
char const* stackBacktrace,
|
|
||||||
char const* fileName,
|
|
||||||
int lineNumber)
|
|
||||||
{
|
{
|
||||||
String s;
|
Log::out() << formattedMessage.toRawUTF8 ();
|
||||||
|
|
||||||
s << "Message = '" << message << "'" << newLine;
|
|
||||||
s << "File = '" << fileName << "' Line " << String (lineNumber) << newLine;
|
|
||||||
s << "Stack Trace:" << newLine;
|
|
||||||
s << stackBacktrace;
|
|
||||||
|
|
||||||
Log::out() << s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -48,7 +43,7 @@ public:
|
|||||||
// We don't really expect the program to run after this
|
// We don't really expect the program to run after this
|
||||||
// but the unit test is here so you can manually test it.
|
// but the unit test is here so you can manually test it.
|
||||||
|
|
||||||
FatalError ("unit test", __FILE__, __LINE__);
|
FatalError ("The unit test intentionally failed", __FILE__, __LINE__);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#ifndef RIPPLE_SCOPEDFATALERRORREPORTER_H_INCLUDED
|
#ifndef RIPPLE_FATALERRORREPORTER_H_INCLUDED
|
||||||
#define RIPPLE_SCOPEDFATALERRORREPORTER_H_INCLUDED
|
#define RIPPLE_FATALERRORREPORTER_H_INCLUDED
|
||||||
|
|
||||||
/** FatalError reporter.
|
/** FatalError reporter.
|
||||||
|
|
||||||
@@ -24,10 +24,7 @@ public:
|
|||||||
FatalErrorReporter ();
|
FatalErrorReporter ();
|
||||||
~FatalErrorReporter ();
|
~FatalErrorReporter ();
|
||||||
|
|
||||||
void onFatalError (char const* message,
|
void reportMessage (String& formattedMessage);
|
||||||
char const* stackBacktrace,
|
|
||||||
char const* fileName,
|
|
||||||
int lineNumber);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user