diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj
index 227c1f85..71e0701f 100644
--- a/Builds/VisualStudio2012/beast.vcxproj
+++ b/Builds/VisualStudio2012/beast.vcxproj
@@ -116,6 +116,7 @@
+
@@ -402,6 +403,10 @@
true
true
+
+ true
+ true
+
true
true
diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters
index 709802ca..873dc89a 100644
--- a/Builds/VisualStudio2012/beast.vcxproj.filters
+++ b/Builds/VisualStudio2012/beast.vcxproj.filters
@@ -44,9 +44,6 @@
{abe24d69-c1d1-49e2-98a1-1e7bf760b97a}
-
- {0fa6b76b-305f-473c-9b94-c1028a3af3fc}
-
{e2339099-bb8e-4437-ae8b-d4f64ef1e3f3}
@@ -140,6 +137,9 @@
{10ef778f-6b81-437e-a6ef-558ff4163acc}
+
+ {0fa6b76b-305f-473c-9b94-c1028a3af3fc}
+
@@ -212,10 +212,10 @@
beast_core\json
- beast_core\logging
+ beast_core\memory\logging
- beast_core\logging
+ beast_core\memory\logging
beast_core\maths
@@ -731,6 +731,9 @@
beast_basics\threads
+
+ beast_core\diagnostic
+
@@ -773,10 +776,10 @@
beast_core\json
- beast_core\logging
+ beast_core\memory\logging
- beast_core\logging
+ beast_core\memory\logging
beast_core\maths
@@ -1141,6 +1144,9 @@
beast_basics\threads
+
+ beast_core\diagnostic
+
diff --git a/TODO.txt b/TODO.txt
index 4d11e8dd..21133462 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -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
diff --git a/modules/beast_core/beast_core.cpp b/modules/beast_core/beast_core.cpp
index becc39af..e3ae5c0f 100644
--- a/modules/beast_core/beast_core.cpp
+++ b/modules/beast_core/beast_core.cpp
@@ -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"
diff --git a/modules/beast_core/beast_core.h b/modules/beast_core/beast_core.h
index 08eceb44..fc0a3361 100644
--- a/modules/beast_core/beast_core.h
+++ b/modules/beast_core/beast_core.h
@@ -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"
diff --git a/modules/beast_core/diagnostic/beast_FatalError.cpp b/modules/beast_core/diagnostic/beast_FatalError.cpp
new file mode 100644
index 00000000..6737f9db
--- /dev/null
+++ b/modules/beast_core/diagnostic/beast_FatalError.cpp
@@ -0,0 +1,109 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ 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 , 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;
diff --git a/modules/beast_core/diagnostic/beast_FatalError.h b/modules/beast_core/diagnostic/beast_FatalError.h
new file mode 100644
index 00000000..130524ea
--- /dev/null
+++ b/modules/beast_core/diagnostic/beast_FatalError.h
@@ -0,0 +1,97 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ 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 , FatalError> s_reporter;
+
+ LockType m_mutex;
+};
+
+#endif
diff --git a/modules/beast_core/diagnostic/beast_ProtectedCall.cpp b/modules/beast_core/diagnostic/beast_ProtectedCall.cpp
index b5b7c190..ae23396c 100644
--- a/modules/beast_core/diagnostic/beast_ProtectedCall.cpp
+++ b/modules/beast_core/diagnostic/beast_ProtectedCall.cpp
@@ -277,7 +277,7 @@ bool CatchAny (Function f, bool returnFromException)
//------------------------------------------------------------------------------
-void ProtectedCall::DefaultHandler::onException (ProtectedCall::Exception const& e) const
+void ProtectedCall::DefaultHandler::onException (ProtectedCall::Exception const&) const
{
}
diff --git a/modules/beast_core/diagnostic/beast_UnitTest.h b/modules/beast_core/diagnostic/beast_UnitTest.h
index 80dbfd83..1f950d9d 100644
--- a/modules/beast_core/diagnostic/beast_UnitTest.h
+++ b/modules/beast_core/diagnostic/beast_UnitTest.h
@@ -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.