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
|
||||
#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.
|
||||
|
||||
Set one of these to manually force a particular implementation of bind().
|
||||
|
||||
@@ -103,7 +103,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_BOOST_IS_AVAILABLE
|
||||
|
||||
This activates boost specific features and improvements.
|
||||
*/
|
||||
#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.
|
||||
|
||||
Set one of these to manually force a particular implementation of bind().
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
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
|
||||
|
||||
- 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;
|
||||
|
||||
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 ()
|
||||
{
|
||||
beginTestCase ("raise");
|
||||
|
||||
TestReporter reporter (*this);
|
||||
|
||||
FatalError::setReporter (reporter);
|
||||
|
||||
// We don't really expect the program to run after this
|
||||
// but the unit test is here so you can manually test it.
|
||||
|
||||
FatalError ("unit test", __FILE__, __LINE__);
|
||||
int shouldBeZero (1);
|
||||
fatal_require (shouldBeZero == 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -36,35 +36,93 @@ class FatalError : Uncopyable
|
||||
public:
|
||||
struct Reporter
|
||||
{
|
||||
virtual ~Reporter () { }
|
||||
|
||||
/** Called when a fatal error is raised.
|
||||
|
||||
Because the program is likely in an inconsistent state, it is a
|
||||
good idea to do as little as possible from within this function.
|
||||
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 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.
|
||||
*/
|
||||
virtual void onFatalError (char const* message,
|
||||
char const* stackBacktrace,
|
||||
char const* fileName,
|
||||
int lineNumber) = 0;
|
||||
char const* filePath,
|
||||
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.
|
||||
|
||||
Note that if a fatal error is raised during the construction of
|
||||
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
|
||||
that have non-trivial constructors, use SharedSingleton instead.
|
||||
The default behavior when no reporter is set is to invoke
|
||||
the base class version of Reporter::onFatalError.
|
||||
|
||||
If a reporter was previously set, this routine will do nothing.
|
||||
|
||||
@see SharedSingleton
|
||||
@see SharedSingleton, Reporter
|
||||
*/
|
||||
static void setReporter (Reporter& reporter);
|
||||
|
||||
@@ -81,13 +139,24 @@ public:
|
||||
other threads will be blocked before the process terminates.
|
||||
|
||||
@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.
|
||||
*/
|
||||
FatalError (char const* message, char const* fileName, int lineNumber);
|
||||
FatalError (char const* message, char const* filePath, int lineNumber);
|
||||
|
||||
private:
|
||||
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
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifdef TWICE
|
||||
#error die
|
||||
#endif
|
||||
|
||||
#define TWICE
|
||||
|
||||
FatalErrorReporter::FatalErrorReporter ()
|
||||
{
|
||||
FatalError::setReporter (*this);
|
||||
@@ -14,20 +20,9 @@ FatalErrorReporter::~FatalErrorReporter ()
|
||||
FatalError::resetReporter (*this);
|
||||
}
|
||||
|
||||
void FatalErrorReporter::onFatalError (
|
||||
char const* message,
|
||||
char const* stackBacktrace,
|
||||
char const* fileName,
|
||||
int lineNumber)
|
||||
void FatalErrorReporter::reportMessage (String& formattedMessage)
|
||||
{
|
||||
String s;
|
||||
|
||||
s << "Message = '" << message << "'" << newLine;
|
||||
s << "File = '" << fileName << "' Line " << String (lineNumber) << newLine;
|
||||
s << "Stack Trace:" << newLine;
|
||||
s << stackBacktrace;
|
||||
|
||||
Log::out() << s;
|
||||
Log::out() << formattedMessage.toRawUTF8 ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -48,7 +43,7 @@ public:
|
||||
// We don't really expect the program to run after this
|
||||
// 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
|
||||
#define RIPPLE_SCOPEDFATALERRORREPORTER_H_INCLUDED
|
||||
#ifndef RIPPLE_FATALERRORREPORTER_H_INCLUDED
|
||||
#define RIPPLE_FATALERRORREPORTER_H_INCLUDED
|
||||
|
||||
/** FatalError reporter.
|
||||
|
||||
@@ -24,10 +24,7 @@ public:
|
||||
FatalErrorReporter ();
|
||||
~FatalErrorReporter ();
|
||||
|
||||
void onFatalError (char const* message,
|
||||
char const* stackBacktrace,
|
||||
char const* fileName,
|
||||
int lineNumber);
|
||||
void reportMessage (String& formattedMessage);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user