Add FatalError

This commit is contained in:
Vinnie Falco
2013-07-30 19:19:16 -07:00
parent db08a5946f
commit 6d83d171c3
9 changed files with 230 additions and 10 deletions

View File

@@ -116,6 +116,7 @@
<ClInclude Include="..\..\modules\beast_core\containers\beast_Variant.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_Debug.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_Error.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_FatalError.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_ProtectedCall.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_FPUFlags.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_LeakChecked.h" />
@@ -402,6 +403,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\beast_FatalError.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\beast_ProtectedCall.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>

View File

@@ -44,9 +44,6 @@
<Filter Include="beast_core\json">
<UniqueIdentifier>{abe24d69-c1d1-49e2-98a1-1e7bf760b97a}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\logging">
<UniqueIdentifier>{0fa6b76b-305f-473c-9b94-c1028a3af3fc}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\maths">
<UniqueIdentifier>{e2339099-bb8e-4437-ae8b-d4f64ef1e3f3}</UniqueIdentifier>
</Filter>
@@ -140,6 +137,9 @@
<Filter Include="beast_sqdb\source">
<UniqueIdentifier>{10ef778f-6b81-437e-a6ef-558ff4163acc}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\memory\logging">
<UniqueIdentifier>{0fa6b76b-305f-473c-9b94-c1028a3af3fc}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\modules\beast_core\beast_core.h">
@@ -212,10 +212,10 @@
<Filter>beast_core\json</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\logging\beast_FileLogger.h">
<Filter>beast_core\logging</Filter>
<Filter>beast_core\memory\logging</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\logging\beast_Logger.h">
<Filter>beast_core\logging</Filter>
<Filter>beast_core\memory\logging</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\maths\beast_BigInteger.h">
<Filter>beast_core\maths</Filter>
@@ -731,6 +731,9 @@
<ClInclude Include="..\..\modules\beast_basics\threads\beast_Workers.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_FatalError.h">
<Filter>beast_core\diagnostic</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\modules\beast_core\beast_core.cpp">
@@ -773,10 +776,10 @@
<Filter>beast_core\json</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\logging\beast_FileLogger.cpp">
<Filter>beast_core\logging</Filter>
<Filter>beast_core\memory\logging</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\logging\beast_Logger.cpp">
<Filter>beast_core\logging</Filter>
<Filter>beast_core\memory\logging</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\maths\beast_BigInteger.cpp">
<Filter>beast_core\maths</Filter>
@@ -1141,6 +1144,9 @@
<ClCompile Include="..\..\modules\beast_basics\threads\beast_Workers.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\beast_FatalError.cpp">
<Filter>beast_core\diagnostic</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\TODO.txt" />

View File

@@ -13,6 +13,7 @@ BEAST TODO
- Return size_t from hash function, take out upperLimit, move mod % to caller
- Make hash function a functor using operator()
- Implement HardenedHashFunctions
- Fix problem with assigning to the result of operator[] maybe use a proxy?
- Set sqlite thread safety model to '2' in beast_sqlite

View File

@@ -146,6 +146,7 @@ namespace beast
#include "diagnostic/beast_Debug.cpp"
#include "diagnostic/beast_Error.cpp"
#include "diagnostic/beast_FatalError.cpp"
#include "diagnostic/beast_FPUFlags.cpp"
#include "diagnostic/beast_LeakChecked.cpp"
#include "diagnostic/beast_ProtectedCall.cpp"

View File

@@ -213,6 +213,8 @@ namespace beast
#include "text/beast_String.h"
#include "threads/beast_CriticalSection.h"
#include "diagnostic/beast_FatalError.h"
#include "diagnostic/beast_SafeBool.h"
#include "diagnostic/beast_Error.h"
#include "diagnostic/beast_Debug.h"
@@ -309,7 +311,6 @@ namespace beast
#include "text/beast_StringPool.h"
#include "text/beast_TextDiff.h"
#include "threads/beast_ChildProcess.h"
#include "threads/beast_CriticalSection.h"
#include "threads/beast_DynamicLibrary.h"
#include "threads/beast_HighResolutionTimer.h"
#include "threads/beast_InterProcessLock.h"

View File

@@ -0,0 +1,109 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
Static::Storage <Atomic <FatalError::Reporter*>, FatalError> FatalError::s_reporter;
void FatalError::setReporter (Reporter& reporter)
{
s_reporter->compareAndSetBool (&reporter, nullptr);
}
void FatalError::resetReporter (Reporter& reporter)
{
s_reporter->compareAndSetBool (nullptr, &reporter);
}
FatalError::FatalError (char const* message, char const* fileName, int lineNumber)
{
LockType::ScopedLockType lock (m_mutex);
String const backtraceString = SystemStats::getStackBacktrace ();
char const* const szStackBacktrace = backtraceString.toRawUTF8 ();
String const fileNameString = File (fileName).getFileName ();
char const* const szFileName = fileNameString.toRawUTF8 ();
Reporter* const reporter = s_reporter->get ();
if (reporter != nullptr)
{
reporter->onFatalError (message, szStackBacktrace, szFileName, lineNumber);
}
Process::terminate ();
}
//------------------------------------------------------------------------------
// Yes even this class can have a unit test. It's manually triggered though.
//
class FatalErrorTests : public UnitTest
{
public:
FatalErrorTests () : UnitTest ("FatalError", "beast", runManual)
{
}
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__);
}
};
static FatalErrorTests fatalErrorTests;

View File

@@ -0,0 +1,97 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_FATALERROR_H_INCLUDED
#define BEAST_FATALERROR_H_INCLUDED
/** Signal a fatal error.
A fatal error indicates that the program has encountered an unexpected
situation and cannot continue safely. Reasons for raising a fatal error
would be to protect data integrity, prevent valuable resources from being
wasted, or to ensure that the user does not experience undefined behavior.
This function will end the process with exit code EXIT_FAILURE. Before
the process is terminated, a listener object gets notified so that the
client application can perform logging or emit further diagnostics.
*/
class FatalError : Uncopyable
{
public:
struct 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.
@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 lineNumber The line number in the source file.
*/
virtual void onFatalError (char const* message,
char const* stackBacktrace,
char const* fileName,
int lineNumber) = 0;
};
/** 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.
The solution is not to use objects with static storage duration
that have non-trivial constructors, use SharedSingleton instead.
If a reporter was previously set, this routine will do nothing.
@see SharedSingleton
*/
static void setReporter (Reporter& reporter);
/** Clear the fatal error reporter.
If the current reporter is the same as the one passed in, this
will remove the reporter.
*/
static void resetReporter (Reporter& reporter);
/** Raise a fatal error.
If multiple threads raise an error, only one will succeed. The
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 lineNumber Pass __LINE__ here.
*/
FatalError (char const* message, char const* fileName, int lineNumber);
private:
typedef CriticalSection LockType;
static Static::Storage <Atomic <Reporter*>, FatalError> s_reporter;
LockType m_mutex;
};
#endif

View File

@@ -277,7 +277,7 @@ bool CatchAny (Function <void (void)> f, bool returnFromException)
//------------------------------------------------------------------------------
void ProtectedCall::DefaultHandler::onException (ProtectedCall::Exception const& e) const
void ProtectedCall::DefaultHandler::onException (ProtectedCall::Exception const&) const
{
}

View File

@@ -64,7 +64,7 @@ class UnitTests;
@see UnitTests
*/
class BEAST_API UnitTest : Uncopyable
class BEAST_API UnitTest : public Uncopyable
{
public:
/** When the test should be run.