mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-29 06:55:49 +00:00
Better unhandled exception handling:
Log thread name and exception type on unhandled exceptions and use a terminate handler to get a stack trace that includes the function that thows the exception.
This commit is contained in:
@@ -86,7 +86,7 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;NO_LOG_UNHANDLED_EXCEPTIONS;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<DisableSpecificWarnings>4800;4244;4267;4018</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4800;4244;4267;4018</DisableSpecificWarnings>
|
||||||
<ExceptionHandling>Async</ExceptionHandling>
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;NO_LOG_UNHANDLED_EXCEPTIONS;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<DisableSpecificWarnings>4800;4244;4267;4018</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4800;4244;4267;4018</DisableSpecificWarnings>
|
||||||
<ExceptionHandling>Async</ExceptionHandling>
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
@@ -160,7 +160,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;NO_LOG_UNHANDLED_EXCEPTIONS;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<DisableSpecificWarnings>4800;4244;4267;4018</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4800;4244;4267;4018</DisableSpecificWarnings>
|
||||||
<ExceptionHandling>Async</ExceptionHandling>
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;NO_LOG_UNHANDLED_EXCEPTIONS;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<DisableSpecificWarnings>4800;4244;4267;4018</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4800;4244;4267;4018</DisableSpecificWarnings>
|
||||||
<ExceptionHandling>Async</ExceptionHandling>
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
@@ -2016,6 +2016,12 @@
|
|||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\core\impl\ThreadEntry.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\core\impl\TimeKeeper.cpp">
|
<ClCompile Include="..\..\src\ripple\core\impl\TimeKeeper.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
@@ -2072,12 +2078,6 @@
|
|||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\core\tests\ReportUncaughtException.test.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
|
||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\src\ripple\core\tests\SociDB.test.cpp">
|
<ClCompile Include="..\..\src\ripple\core\tests\SociDB.test.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
|
|||||||
@@ -2553,6 +2553,9 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\core\impl\Stoppable.cpp">
|
<ClCompile Include="..\..\src\ripple\core\impl\Stoppable.cpp">
|
||||||
<Filter>ripple\core\impl</Filter>
|
<Filter>ripple\core\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\core\impl\ThreadEntry.cpp">
|
||||||
|
<Filter>ripple\core\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\core\impl\TimeKeeper.cpp">
|
<ClCompile Include="..\..\src\ripple\core\impl\TimeKeeper.cpp">
|
||||||
<Filter>ripple\core\impl</Filter>
|
<Filter>ripple\core\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -2607,9 +2610,6 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\core\tests\LoadFeeTrack.test.cpp">
|
<ClCompile Include="..\..\src\ripple\core\tests\LoadFeeTrack.test.cpp">
|
||||||
<Filter>ripple\core\tests</Filter>
|
<Filter>ripple\core\tests</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\core\tests\ReportUncaughtException.test.cpp">
|
|
||||||
<Filter>ripple\core\tests</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\src\ripple\core\tests\SociDB.test.cpp">
|
<ClCompile Include="..\..\src\ripple\core\tests\SociDB.test.cpp">
|
||||||
<Filter>ripple\core\tests</Filter>
|
<Filter>ripple\core\tests</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -365,7 +365,6 @@ def config_base(env):
|
|||||||
,{'SOCI_CXX_C11' : '1'}
|
,{'SOCI_CXX_C11' : '1'}
|
||||||
,'_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS'
|
,'_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS'
|
||||||
,'BOOST_NO_AUTO_PTR'
|
,'BOOST_NO_AUTO_PTR'
|
||||||
,'NO_LOG_UNHANDLED_EXCEPTIONS'
|
|
||||||
])
|
])
|
||||||
|
|
||||||
if Beast.system.windows:
|
if Beast.system.windows:
|
||||||
@@ -385,6 +384,7 @@ def config_base(env):
|
|||||||
openssl = os.path.join(OSX_OPENSSL_ROOT, most_recent)
|
openssl = os.path.join(OSX_OPENSSL_ROOT, most_recent)
|
||||||
env.Prepend(CPPPATH='%s/include' % openssl)
|
env.Prepend(CPPPATH='%s/include' % openssl)
|
||||||
env.Prepend(LIBPATH=['%s/lib' % openssl])
|
env.Prepend(LIBPATH=['%s/lib' % openssl])
|
||||||
|
env.Append(CPPDEFINES=['NO_LOG_UNHANDLED_EXCEPTIONS'])
|
||||||
|
|
||||||
# handle command-line arguments
|
# handle command-line arguments
|
||||||
profile_jemalloc = ARGUMENTS.get('profile-jemalloc')
|
profile_jemalloc = ARGUMENTS.get('profile-jemalloc')
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <ripple/basics/ThreadName.h>
|
#include <ripple/basics/ThreadName.h>
|
||||||
#include <ripple/core/Config.h>
|
#include <ripple/core/Config.h>
|
||||||
#include <ripple/core/ConfigSections.h>
|
#include <ripple/core/ConfigSections.h>
|
||||||
|
#include <ripple/core/ThreadEntry.h>
|
||||||
#include <ripple/core/TimeKeeper.h>
|
#include <ripple/core/TimeKeeper.h>
|
||||||
#include <ripple/crypto/csprng.h>
|
#include <ripple/crypto/csprng.h>
|
||||||
#include <ripple/json/to_string.h>
|
#include <ripple/json/to_string.h>
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
#if defined(BEAST_LINUX) || defined(BEAST_MAC) || defined(BEAST_BSD)
|
#if defined(BEAST_LINUX) || defined(BEAST_MAC) || defined(BEAST_BSD)
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -452,7 +454,8 @@ int run (int argc, char** argv)
|
|||||||
app->doStart();
|
app->doStart();
|
||||||
|
|
||||||
// Block until we get a stop RPC.
|
// Block until we get a stop RPC.
|
||||||
app->run();
|
ripple::threadEntry (
|
||||||
|
app.get(), &Application::run, "Main::run()");
|
||||||
|
|
||||||
// Try to write out some entropy to use the next time we start.
|
// Try to write out some entropy to use the next time we start.
|
||||||
auto entropy = getEntropyFile (app->config());
|
auto entropy = getEntropyFile (app->config());
|
||||||
@@ -517,6 +520,9 @@ int main (int argc, char** argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
atexit(&google::protobuf::ShutdownProtobufLibrary);
|
atexit(&google::protobuf::ShutdownProtobufLibrary);
|
||||||
|
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
|
||||||
|
std::set_terminate(ripple::terminateHandler);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto const result (ripple::run (argc, argv));
|
auto const result (ripple::run (argc, argv));
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#ifndef RIPPLE_BASICS_CONTRACT_H_INCLUDED
|
#ifndef RIPPLE_BASICS_CONTRACT_H_INCLUDED
|
||||||
#define RIPPLE_BASICS_CONTRACT_H_INCLUDED
|
#define RIPPLE_BASICS_CONTRACT_H_INCLUDED
|
||||||
|
|
||||||
|
#include <ripple/beast/type_name.h>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
@@ -62,7 +63,8 @@ Throw (Args&&... args)
|
|||||||
"Exception must derive from std::exception.");
|
"Exception must derive from std::exception.");
|
||||||
|
|
||||||
E e(std::forward<Args>(args)...);
|
E e(std::forward<Args>(args)...);
|
||||||
LogThrow (std::string("Throwing exception: ") + e.what());
|
LogThrow (std::string("Throwing exception of type " +
|
||||||
|
beast::type_name<E>() +": ") + e.what());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,35 +20,35 @@
|
|||||||
#ifndef RIPPLE_CORE_THREAD_ENTRY_H_INCLUDED
|
#ifndef RIPPLE_CORE_THREAD_ENTRY_H_INCLUDED
|
||||||
#define RIPPLE_CORE_THREAD_ENTRY_H_INCLUDED
|
#define RIPPLE_CORE_THREAD_ENTRY_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/basics/Log.h>
|
|
||||||
#include <boost/coroutine/exceptions.hpp> // forced_unwind exception
|
|
||||||
#include <exception>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace ripple
|
namespace ripple
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
void setThreadName(std::string name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminateHandler();
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Report uncaught exceptions to DebugLog and cerr
|
Report uncaught exceptions to DebugLog and cerr
|
||||||
|
|
||||||
Catch all exceptions that escape the called function. Report as much
|
The actual reporting occurs in a terminate handler. This function
|
||||||
information as can be extracted from the exception to both the DebugLog
|
stores information about which thread is running in thread local
|
||||||
and cerr.
|
storage. That way the terminate handler can report not just the
|
||||||
|
exception, but also the thread the exception was thrown in.
|
||||||
|
|
||||||
The idea is to use this routine at the top of a thread, since on
|
The idea is to use this routine at the top of a thread, since on
|
||||||
many platforms the stack trace for an uncaught exception on a thread
|
many platforms the stack trace for an uncaught exception on a thread
|
||||||
is almost useless.
|
is almost useless.
|
||||||
|
|
||||||
For those platforms where the stack trace from an uncaught exception is
|
For those platforms where the stack trace from an uncaught exception is
|
||||||
useful (e.g., OS X) this routine is a no-op. That way a catch will not
|
useful (e.g., OS X) this routine is turned into a no-op (because the
|
||||||
interfere with the stack trace showing the real source of the uncaught
|
preprocessor symbol NO_LOG_UNHANDLED_EXCEPTIONS is defined).
|
||||||
exception.
|
|
||||||
|
|
||||||
Note that any extra information is passed using a lambda because we only
|
|
||||||
want to do the work of building the string in the unlikely event of an
|
|
||||||
uncaught exception. The lambda is only called in the error case.
|
|
||||||
|
|
||||||
Usage example
|
Usage example
|
||||||
|
|
||||||
@@ -87,65 +87,15 @@ int main ()
|
|||||||
@param t Pointer to object to call.
|
@param t Pointer to object to call.
|
||||||
@param threadTop Pointer to member function of t to call.
|
@param threadTop Pointer to member function of t to call.
|
||||||
@param name Name of function to log.
|
@param name Name of function to log.
|
||||||
@param lamdba Optional lambda that returns additional text for the log.
|
|
||||||
*/
|
*/
|
||||||
template <typename T, typename R, typename L>
|
|
||||||
void threadEntry (
|
|
||||||
T* t, R (T::*threadTop) (), char const* name, L&& lambda)
|
|
||||||
{
|
|
||||||
// Enforce that lambda takes no parameters and returns std::string.
|
|
||||||
static_assert (
|
|
||||||
std::is_convertible<decltype (lambda()), std::string const>::value,
|
|
||||||
"Last argument must be a lamdba taking no arguments "
|
|
||||||
"and returning std::string.");
|
|
||||||
|
|
||||||
#ifdef NO_LOG_UNHANDLED_EXCEPTIONS
|
|
||||||
// Don't use a try block so we can get a good call stack.
|
|
||||||
((t)->*(threadTop)) ();
|
|
||||||
#else
|
|
||||||
// Local lambda for string formatting and re-throwing.
|
|
||||||
auto logUncaughtException =
|
|
||||||
[name, &lambda] (char const* exName)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "Unhandled exception in " << name
|
|
||||||
<< "; Exception: " << exName;
|
|
||||||
|
|
||||||
std::string extra = lambda();
|
|
||||||
if (! extra.empty())
|
|
||||||
ss << "; " << extra;
|
|
||||||
|
|
||||||
JLOG(debugLog().fatal()) << ss.str();
|
|
||||||
std::cerr << ss.str() << std::endl;
|
|
||||||
throw;
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Call passed in member function.
|
|
||||||
((t)->*(threadTop)) ();
|
|
||||||
}
|
|
||||||
catch (std::exception const& ex)
|
|
||||||
{
|
|
||||||
logUncaughtException (ex.what());
|
|
||||||
}
|
|
||||||
catch (boost::coroutines::detail::forced_unwind const&)
|
|
||||||
{
|
|
||||||
logUncaughtException ("forced_unwind");
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
logUncaughtException ("unknown exception type");
|
|
||||||
}
|
|
||||||
#endif // NO_LOG_UNHANDLED_EXCEPTIONS else
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the common case where there is no additional local information.
|
|
||||||
template <typename T, typename R>
|
template <typename T, typename R>
|
||||||
inline void threadEntry (
|
void threadEntry (
|
||||||
T* t, R (T::*threadTop) (), char const* name)
|
T* t, R (T::*threadTop) (), std::string name)
|
||||||
{
|
{
|
||||||
threadEntry (t, threadTop, name, []{ return std::string(); });
|
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
|
||||||
|
detail::setThreadName (std::move(name));
|
||||||
|
#endif
|
||||||
|
((t)->*(threadTop)) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -77,15 +77,12 @@ bool Job::shouldCancel () const
|
|||||||
|
|
||||||
void Job::doJob ()
|
void Job::doJob ()
|
||||||
{
|
{
|
||||||
threadEntry (this, &Job::doJobImpl, "Job::doJob()",
|
std::stringstream ss;
|
||||||
[this] ()
|
ss << "Job::doJob(); Job name: "
|
||||||
{
|
<< mName << "; Job type: " << mType
|
||||||
std::stringstream ss;
|
<< "; Job info: " << mJob.target_type ().name ();
|
||||||
ss << "Job name: " << this->mName
|
|
||||||
<< "; Job type: " << this->mType
|
threadEntry (this, &Job::doJobImpl, ss.str());
|
||||||
<< "; Job info: " << this->mJob.target_type().name();
|
|
||||||
return ss.str();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Job::rename (std::string const& newName)
|
void Job::rename (std::string const& newName)
|
||||||
|
|||||||
71
src/ripple/core/impl/ThreadEntry.cpp
Normal file
71
src/ripple/core/impl/ThreadEntry.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <BeastConfig.h>
|
||||||
|
#include <ripple/core/ThreadEntry.h>
|
||||||
|
#include <ripple/basics/Log.h>
|
||||||
|
|
||||||
|
#include <boost/coroutine/exceptions.hpp>
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
|
||||||
|
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
|
||||||
|
namespace detail {
|
||||||
|
thread_local
|
||||||
|
std::string threadName;
|
||||||
|
|
||||||
|
void setThreadName(std::string name)
|
||||||
|
{
|
||||||
|
threadName = std::move(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminateHandler()
|
||||||
|
{
|
||||||
|
if (std::current_exception())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << detail::threadName << ": " << e.what () << '\n';
|
||||||
|
JLOG(debugLog().fatal())
|
||||||
|
<< detail::threadName << ": " << e.what () << '\n';
|
||||||
|
}
|
||||||
|
catch (boost::coroutines::detail::forced_unwind const&)
|
||||||
|
{
|
||||||
|
std::cerr << detail::threadName << ": forced_unwind\n";
|
||||||
|
JLOG(debugLog().fatal())
|
||||||
|
<< detail::threadName << ": forced_unwind\n";
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << detail::threadName << ": unknown exception\n";
|
||||||
|
JLOG (debugLog ().fatal ())
|
||||||
|
<< detail::threadName << ": unknown exception\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
@@ -160,10 +160,7 @@ void Workers::Worker::run ()
|
|||||||
{
|
{
|
||||||
// Call runImpl() and report if any exceptions escape runImpl.
|
// Call runImpl() and report if any exceptions escape runImpl.
|
||||||
threadEntry (this, &Workers::Worker::runImpl,
|
threadEntry (this, &Workers::Worker::runImpl,
|
||||||
"Workers::Worker::run()", [this] ()
|
"Workers::Worker::run(); Thread: " + Thread::getThreadName());
|
||||||
{
|
|
||||||
return "Thread: " + Thread::getThreadName();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workers::Worker::runImpl ()
|
void Workers::Worker::runImpl ()
|
||||||
|
|||||||
@@ -1,169 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2016 Ripple Labs Inc.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <BeastConfig.h>
|
|
||||||
|
|
||||||
#include <ripple/basics/Log.h>
|
|
||||||
#include <ripple/basics/TestSuite.h>
|
|
||||||
#include <ripple/core/ThreadEntry.h>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
// threadEntry is disabled if NO_LOG_UNHANDLED_EXCEPTIONS is defined.
|
|
||||||
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
|
|
||||||
|
|
||||||
class ReportUncaughtException_test : public TestSuite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class TestSink : public beast::Journal::Sink
|
|
||||||
{
|
|
||||||
std::stringstream ss_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
TestSink()
|
|
||||||
: Sink (beast::severities::kFatal, false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getText() const
|
|
||||||
{
|
|
||||||
return ss_.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
ss_.str("");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
write (beast::severities::Severity level, std::string const& s) override
|
|
||||||
{
|
|
||||||
if (level >= threshold())
|
|
||||||
ss_ << s;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ExceptionGen
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// A place to keep methods that throw.
|
|
||||||
void dontThrow()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void throwStdExcept()
|
|
||||||
{
|
|
||||||
throw std::logic_error ("logic_error");
|
|
||||||
}
|
|
||||||
|
|
||||||
void throwForcedUnwind()
|
|
||||||
{
|
|
||||||
throw boost::coroutines::detail::forced_unwind ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void throwWeird()
|
|
||||||
{
|
|
||||||
throw std::string ("Pretty unusual...");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void test ()
|
|
||||||
{
|
|
||||||
// Install our own debug Sink so we can see what gets written.
|
|
||||||
// Retain the old Sink so we can put it back.
|
|
||||||
auto testSink = std::make_unique<TestSink>();
|
|
||||||
TestSink& sinkRef = *testSink;
|
|
||||||
std::unique_ptr<beast::Journal::Sink> oldSink =
|
|
||||||
setDebugLogSink (std::move (testSink));
|
|
||||||
|
|
||||||
ExceptionGen exGen;
|
|
||||||
|
|
||||||
// Make sure nothing gets logged if there's no exception.
|
|
||||||
threadEntry (&exGen, &ExceptionGen::dontThrow, "noThrow");
|
|
||||||
expect (sinkRef.getText() == "");
|
|
||||||
sinkRef.reset();
|
|
||||||
|
|
||||||
threadEntry (&exGen, &ExceptionGen::dontThrow, "noThrow",
|
|
||||||
[] { return "Just noise"; });
|
|
||||||
|
|
||||||
expect (sinkRef.getText() == "");
|
|
||||||
sinkRef.reset();
|
|
||||||
|
|
||||||
using PExGenMemFn = void (ExceptionGen::*) ();
|
|
||||||
auto testCase = [this, &exGen, &sinkRef] (
|
|
||||||
PExGenMemFn call, char const* description)
|
|
||||||
{
|
|
||||||
std::string want = std::string ("Unhandled exception in "
|
|
||||||
"testFn; Exception: ") + description;
|
|
||||||
|
|
||||||
// Test the case without the closing lambda.
|
|
||||||
bool gotException = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
threadEntry (&exGen, call, "testFn");
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
gotException = true;
|
|
||||||
}
|
|
||||||
expect (gotException == true);
|
|
||||||
expect (sinkRef.getText() == want);
|
|
||||||
sinkRef.reset();
|
|
||||||
|
|
||||||
// Try the case with the closing lambda.
|
|
||||||
gotException = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
threadEntry (&exGen, call, "testFn",
|
|
||||||
[]{ return "extra info"; });
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
gotException = true;
|
|
||||||
}
|
|
||||||
expect (gotException == true);
|
|
||||||
expect (sinkRef.getText() == want + "; extra info");
|
|
||||||
sinkRef.reset();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test logging for a stad::exception.
|
|
||||||
testCase (&ExceptionGen::throwStdExcept, "logic_error");
|
|
||||||
|
|
||||||
// Test logging for a forced_unwind.
|
|
||||||
testCase (&ExceptionGen::throwForcedUnwind, "forced_unwind");
|
|
||||||
|
|
||||||
// Test logging for none of the above.
|
|
||||||
testCase (&ExceptionGen::throwWeird, "unknown exception type");
|
|
||||||
|
|
||||||
// We're done with TestSink. Re-install the old Sink.
|
|
||||||
setDebugLogSink (std::move (oldSink));
|
|
||||||
}
|
|
||||||
|
|
||||||
void run ()
|
|
||||||
{
|
|
||||||
test ();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE (ReportUncaughtException, core, ripple);
|
|
||||||
|
|
||||||
#endif // NO_LOG_UNHANDLED_EXCEPTIONS
|
|
||||||
|
|
||||||
} // ripple
|
|
||||||
@@ -30,11 +30,11 @@
|
|||||||
#include <ripple/core/impl/SNTPClock.cpp>
|
#include <ripple/core/impl/SNTPClock.cpp>
|
||||||
#include <ripple/core/impl/Stoppable.cpp>
|
#include <ripple/core/impl/Stoppable.cpp>
|
||||||
#include <ripple/core/impl/TimeKeeper.cpp>
|
#include <ripple/core/impl/TimeKeeper.cpp>
|
||||||
|
#include <ripple/core/impl/ThreadEntry.cpp>
|
||||||
#include <ripple/core/impl/Workers.cpp>
|
#include <ripple/core/impl/Workers.cpp>
|
||||||
|
|
||||||
#include <ripple/core/tests/Config.test.cpp>
|
#include <ripple/core/tests/Config.test.cpp>
|
||||||
#include <ripple/core/tests/Coroutine.test.cpp>
|
#include <ripple/core/tests/Coroutine.test.cpp>
|
||||||
#include <ripple/core/tests/LoadFeeTrack.test.cpp>
|
#include <ripple/core/tests/LoadFeeTrack.test.cpp>
|
||||||
#include <ripple/core/tests/ReportUncaughtException.test.cpp>
|
|
||||||
#include <ripple/core/tests/Stoppable.test.cpp>
|
#include <ripple/core/tests/Stoppable.test.cpp>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user