Remove beast::Thread (RIPD-1189):

All uses of beast::Thread were previously removed from the code
base, so beast::Thread is removed.  One piece of beast::Thread
needed to be preserved: the ability to set the current thread's
name.  So there's now a beast::CurrentThreadName that allows the
current thread's name to be set and returned.

Thread naming is also cleaned up a bit.  ThreadName.h and .cpp
are removed since beast::CurrentThreadName does a better job.
ThreadEntry is also removed, but its terminateHandler() is
preserved in TerminateHandler.cpp.  The revised terminateHandler()
uses beast::CurrentThreadName to recover the name of the running
thread.

Finally, the NO_LOG_UNHANDLED_EXCEPTIONS #define is removed since
it was discovered that the MacOS debugger preserves the stack
of the original throw even if the terminateHandler() rethrows.
This commit is contained in:
Scott Schurr
2017-01-06 17:59:21 -08:00
committed by seelabs
parent 2c6b0f3193
commit ce9238b389
42 changed files with 546 additions and 891 deletions

View File

@@ -527,8 +527,7 @@ macro(setup_build_boilerplate)
endif()
if (APPLE)
add_definitions(-DBEAST_COMPILE_OBJECTIVE_CPP=1
-DNO_LOG_UNHANDLED_EXCEPTIONS)
add_definitions(-DBEAST_COMPILE_OBJECTIVE_CPP=1)
add_compile_options(
-Wno-deprecated -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-function)
endif()

View File

@@ -1465,10 +1465,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\basics\impl\ThreadName.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\basics\impl\Time.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -1513,8 +1509,6 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\TaggedCache.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\ThreadName.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\ToString.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\UnorderedContainers.h">
@@ -1581,6 +1575,11 @@
<ClCompile Include="..\..\src\ripple\beast\core\core.unity.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\beast\core\CurrentThreadName.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\beast\core\CurrentThreadName.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\core\LexicalCast.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\beast\core\linux_SystemStats.cpp">
@@ -1616,11 +1615,6 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\beast\core\SystemStats.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\beast\core\Thread.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\beast\core\Thread.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\beast\core\Time.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
@@ -1937,7 +1931,7 @@
<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\ThreadEntry.cpp">
<ClCompile Include="..\..\src\ripple\core\impl\TerminateHandler.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>
@@ -1975,7 +1969,7 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\Stoppable.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\ThreadEntry.h">
<ClInclude Include="..\..\src\ripple\core\TerminateHandler.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\TimeKeeper.h">
</ClInclude>
@@ -4353,6 +4347,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_CurrentThreadName_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_Debug_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -4437,6 +4435,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\core\TerminateHandler_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\core\Workers_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>

View File

@@ -1980,9 +1980,6 @@
<ClCompile Include="..\..\src\ripple\basics\impl\Sustain.cpp">
<Filter>ripple\basics\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\basics\impl\ThreadName.cpp">
<Filter>ripple\basics\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\basics\impl\Time.cpp">
<Filter>ripple\basics\impl</Filter>
</ClCompile>
@@ -2043,9 +2040,6 @@
<ClInclude Include="..\..\src\ripple\basics\TaggedCache.h">
<Filter>ripple\basics</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\ThreadName.h">
<Filter>ripple\basics</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\ToString.h">
<Filter>ripple\basics</Filter>
</ClInclude>
@@ -2142,6 +2136,12 @@
<ClCompile Include="..\..\src\ripple\beast\core\core.unity.cpp">
<Filter>ripple\beast\core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\beast\core\CurrentThreadName.cpp">
<Filter>ripple\beast\core</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\beast\core\CurrentThreadName.h">
<Filter>ripple\beast\core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\core\LexicalCast.h">
<Filter>ripple\beast\core</Filter>
</ClInclude>
@@ -2190,12 +2190,6 @@
<ClInclude Include="..\..\src\ripple\beast\core\SystemStats.h">
<Filter>ripple\beast\core</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\beast\core\Thread.cpp">
<Filter>ripple\beast\core</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\beast\core\Thread.h">
<Filter>ripple\beast\core</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\beast\core\Time.cpp">
<Filter>ripple\beast\core</Filter>
</ClCompile>
@@ -2532,7 +2526,7 @@
<ClCompile Include="..\..\src\ripple\core\impl\Stoppable.cpp">
<Filter>ripple\core\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\core\impl\ThreadEntry.cpp">
<ClCompile Include="..\..\src\ripple\core\impl\TerminateHandler.cpp">
<Filter>ripple\core\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\core\impl\TimeKeeper.cpp">
@@ -2571,7 +2565,7 @@
<ClInclude Include="..\..\src\ripple\core\Stoppable.h">
<Filter>ripple\core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\ThreadEntry.h">
<ClInclude Include="..\..\src\ripple\core\TerminateHandler.h">
<Filter>ripple\core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\TimeKeeper.h">
@@ -5109,6 +5103,9 @@
<ClCompile Include="..\..\src\test\beast\beast_basic_seconds_clock_test.cpp">
<Filter>test\beast</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_CurrentThreadName_test.cpp">
<Filter>test\beast</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_Debug_test.cpp">
<Filter>test\beast</Filter>
</ClCompile>
@@ -5172,6 +5169,9 @@
<ClCompile Include="..\..\src\test\core\Stoppable_test.cpp">
<Filter>test\core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test\core\TerminateHandler_test.cpp">
<Filter>test\core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test\core\Workers_test.cpp">
<Filter>test\core</Filter>
</ClCompile>

View File

@@ -392,8 +392,6 @@ def config_base(env):
env.Prepend(LIBPATH=['%s/lib' % openssl])
except:
pass
if not 'vcxproj' in COMMAND_LINE_TARGETS:
env.Append(CPPDEFINES=['NO_LOG_UNHANDLED_EXCEPTIONS'])
# handle command-line arguments
profile_jemalloc = ARGUMENTS.get('profile-jemalloc')
@@ -965,7 +963,7 @@ def get_classic_sources(toolchain):
append_sources(result, *list_sources('src/test/shamap', '.cpp'))
append_sources(result, *list_sources('src/test/jtx', '.cpp'))
if use_shp(toolchain):
cc_flags = {'CCFLAGS': ['--system-header-prefix=rocksdb2']}
else:

View File

@@ -22,9 +22,8 @@
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/misc/LoadFeeTrack.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/beast/core/CurrentThreadName.h>
namespace ripple {
namespace detail {
@@ -243,13 +242,7 @@ private:
void run ()
{
threadEntry (
this, &LedgerCleanerImp::runImpl, "LedgerCleanerImp::run()");
}
void runImpl ()
{
beast::Thread::setCurrentThreadName ("LedgerCleaner");
beast::setCurrentThreadName ("LedgerCleaner");
JLOG (j_.debug()) << "Started";
init();

View File

@@ -19,8 +19,7 @@
#include <BeastConfig.h>
#include <ripple/app/main/BasicApp.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/beast/core/CurrentThreadName.h>
BasicApp::BasicApp(std::size_t numberOfThreads)
{
@@ -30,13 +29,10 @@ BasicApp::BasicApp(std::size_t numberOfThreads)
threads_.emplace_back(
[this, numberOfThreads]()
{
beast::Thread::setCurrentThreadName(
beast::setCurrentThreadName(
std::string("io_service #") +
std::to_string(numberOfThreads));
ripple::threadEntry (&io_service_,
&boost::asio::io_service::run,
"io_service::run");
this->io_service_.run();
});
}

View File

@@ -23,9 +23,8 @@
#include <ripple/app/misc/LoadFeeTrack.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/basics/UptimeTimer.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/json/to_string.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <memory>
#include <mutex>
#include <thread>
@@ -108,12 +107,7 @@ void LoadManager::onStop ()
void LoadManager::run ()
{
threadEntry (this, &LoadManager::runImpl, "LoadManager::run()");
}
void LoadManager::runImpl ()
{
beast::Thread::setCurrentThreadName ("LoadManager");
beast::setCurrentThreadName ("LoadManager");
using clock_type = std::chrono::steady_clock;

View File

@@ -97,7 +97,6 @@ public:
private:
void run ();
void runImpl ();
private:
Application& app_;

View File

@@ -25,10 +25,9 @@
#include <ripple/basics/contract.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/Sustain.h>
#include <ripple/basics/ThreadName.h>
#include <ripple/core/Config.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/core/TerminateHandler.h>
#include <ripple/core/TimeKeeper.h>
#include <ripple/crypto/csprng.h>
#include <ripple/json/to_string.h>
@@ -37,6 +36,7 @@
#include <ripple/rpc/RPCHandler.h>
#include <ripple/protocol/BuildInfo.h>
#include <ripple/beast/clock/basic_seconds_clock.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <ripple/beast/core/Time.h>
#include <ripple/beast/utility/Debug.h>
#include <beast/unit_test/dstream.hpp>
@@ -190,7 +190,7 @@ int run (int argc, char** argv)
using namespace std;
setCallingThreadName ("main");
beast::setCurrentThreadName ("rippled: main");
po::variables_map vm;
@@ -453,8 +453,7 @@ int run (int argc, char** argv)
app->doStart();
// Block until we get a stop RPC.
ripple::threadEntry (
app.get(), &Application::run, "Main::run()");
app->run();
// Try to write out some entropy to use the next time we start.
auto entropy = getEntropyFile (app->config());
@@ -465,7 +464,7 @@ int run (int argc, char** argv)
}
// We have an RPC command to process:
setCallingThreadName ("rpc");
beast::setCurrentThreadName ("rippled: rpc");
return RPCCall::fromCommandLine (
*config,
vm["parameters"].as<std::vector<std::string>>(),
@@ -519,9 +518,8 @@ int main (int argc, char** argv)
#endif
atexit(&google::protobuf::ShutdownProtobufLibrary);
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
std::set_terminate(ripple::terminateHandler);
#endif
auto const result (ripple::run (argc, argv));

View File

@@ -25,7 +25,7 @@
#include <ripple/app/main/Application.h>
#include <ripple/basics/contract.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <boost/format.hpp>
#include <boost/format.hpp>
#include <boost/optional.hpp>
@@ -298,13 +298,7 @@ SHAMapStoreImp::copyNode (std::uint64_t& nodeCount,
void
SHAMapStoreImp::run()
{
threadEntry (
this, &SHAMapStoreImp::runImpl, "SHAMapStoreImp::run()");
}
void
SHAMapStoreImp::runImpl()
{
beast::setCurrentThreadName ("SHAMapStore");
LedgerIndex lastRotated = state_db_.getState().lastRotated;
netOPs_ = &app_.getOPs();
ledgerMaster_ = &app_.getLedgerMaster();

View File

@@ -175,7 +175,6 @@ private:
// callback for visitNodes
bool copyNode (std::uint64_t& nodeCount, SHAMapAbstractNode const &node);
void run();
void runImpl();
void dbPaths();
std::shared_ptr <NodeStore::Backend> makeBackendRotating (
std::string path = std::string());

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/basics/Sustain.h>
#include <ripple/basics/ThreadName.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <boost/format.hpp>
// For Sustain Linux variants
@@ -103,7 +103,7 @@ std::string DoSustain ()
auto cc = std::to_string (childCount);
if (pChild == 0)
{
setCallingThreadName ("main");
beast::setCurrentThreadName ("rippled: main");
signal (SIGINT, SIG_DFL);
signal (SIGHUP, SIG_DFL);
signal (SIGUSR1, SIG_DFL);
@@ -111,7 +111,7 @@ std::string DoSustain ()
return "Launching child " + cc;
}
setCallingThreadName (("#" + cc).c_str());
beast::setCurrentThreadName (("rippled: #" + cc).c_str());
sleep (sleepBeforeWaiting);

View File

@@ -1,106 +0,0 @@
//------------------------------------------------------------------------------
/*
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>
#if _MSC_VER
#include <windows.h>
namespace ripple {
// VFALCO TODO use beast::Thread::setCurrentThreadName() or something similar.
void setCallingThreadName (char const* threadName)
{
struct ThreadInfo
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
};
ThreadInfo info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = GetCurrentThreadId ();
info.dwFlags = 0;
__try
{
// This is a VisualStudio specific exception
RaiseException (0x406d1388, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
}
} // ripple
#else
namespace ripple {
#ifdef PR_SET_NAME
#define HAVE_NAME_THREAD
extern void setCallingThreadName (const char* n)
{
static std::string pName;
if (pName.empty ())
{
std::ifstream cLine ("/proc/self/cmdline", std::ios::in);
cLine >> pName;
if (pName.empty ())
pName = "rippled";
else
{
size_t zero = pName.find_first_of ('\0');
if ((zero != std::string::npos) && (zero != 0))
pName = pName.substr (0, zero);
size_t slash = pName.find_last_of ('/');
if (slash != std::string::npos)
pName = pName.substr (slash + 1);
}
pName += " ";
}
// VFALCO TODO Use beast::Thread::setCurrentThreadName here
//
prctl (PR_SET_NAME, (pName + n).c_str (), 0, 0, 0);
}
#endif
#ifndef HAVE_NAME_THREAD
extern void setCallingThreadName (const char*)
{
}
#endif
} // ripple
#endif

View File

@@ -19,7 +19,6 @@
#include <BeastConfig.h>
#include <ripple/basics/UptimeTimer.h>
#include <ripple/beast/core/Thread.h>
#include <atomic>

View File

@@ -0,0 +1,145 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.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.
*/
//==============================================================================
#include <ripple/beast/core/CurrentThreadName.h>
#include <boost/thread/tss.hpp>
namespace beast {
namespace detail {
static boost::thread_specific_ptr<std::string> threadName;
void saveThreadName (std::string name)
{
threadName.reset (new std::string {std::move(name)});
}
} // detail
boost::optional<std::string> getCurrentThreadName ()
{
if (auto r = detail::threadName.get())
return *r;
return boost::none;
}
} // beast
//------------------------------------------------------------------------------
#if BEAST_WINDOWS
#include <windows.h>
#include <process.h>
#include <tchar.h>
namespace beast {
namespace detail {
void setCurrentThreadNameImpl (std::string const& name)
{
#if BEAST_DEBUG && BEAST_MSVC
struct
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} info;
info.dwType = 0x1000;
info.szName = name.c_str ();
info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try
{
RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{}
#else
(void) name;
#endif
}
} // detail
} // beast
//------------------------------------------------------------------------------
#else
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#if BEAST_BSD
// ???
#elif BEAST_MAC || BEAST_IOS
#include <Foundation/NSThread.h>
#include <Foundation/NSString.h>
#import <objc/message.h>
namespace beast{
#include <ripple/beast/core/osx_ObjCHelpers.h>
}
#else
#include <sys/prctl.h>
#endif
namespace beast {
namespace detail {
void setCurrentThreadNameImpl (std::string const& name)
{
#if BEAST_IOS || (BEAST_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
BEAST_AUTORELEASEPOOL
{
[[NSThread currentThread] setName: stringToNS (name)];
}
#elif BEAST_LINUX
#if (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
pthread_setname_np (pthread_self(), name.c_str ());
#else
prctl (PR_SET_NAME, name.c_str (), 0, 0, 0);
#endif
#endif
}
} // detail
} // beast
#endif
namespace beast {
void setCurrentThreadName (std::string name)
{
detail::setCurrentThreadNameImpl (name);
detail::saveThreadName (std::move (name));
}
} // beast

View File

@@ -0,0 +1,48 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.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_CORE_CURRENT_THREAD_NAME_H_INCLUDED
#define BEAST_CORE_CURRENT_THREAD_NAME_H_INCLUDED
#include <boost/optional.hpp>
#include <string>
namespace beast {
/** Changes the name of the caller thread.
Different OSes may place different length or content limits on this name.
*/
void setCurrentThreadName (std::string newThreadName);
/** Returns the name of the caller thread.
The name returned is the name as set by a call to setCurrentThreadName().
If the thread name is set by an external force, then that name change
will not be reported. If no name has ever been set, then boost::none
is returned.
*/
boost::optional<std::string> getCurrentThreadName ();
}
#endif

View File

@@ -1,293 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.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.
*/
//==============================================================================
#include <ripple/beast/core/Thread.h>
#include <ripple/beast/core/SharedObject.h>
#include <ripple/beast/core/SharedPtr.h>
#include <cassert>
#include <thread>
namespace beast {
Thread::Thread (std::string const& threadName_)
: threadName (threadName_),
threadHandle (nullptr),
shouldExit (false)
{
}
Thread::~Thread()
{
/* If your thread class's destructor has been called without first stopping the thread, that
means that this partially destructed object is still performing some work - and that's
probably a Bad Thing!
To avoid this type of nastiness, always make sure you call stopThread() before or during
your subclass's destructor.
*/
assert (! isThreadRunning());
stopThread ();
}
//==============================================================================
void Thread::threadEntryPoint()
{
if (!threadName.empty ())
setCurrentThreadName (threadName);
if (startSuspensionEvent.wait (10000))
run();
closeThreadHandle();
}
// used to wrap the incoming call from the platform-specific code
void beast_threadEntryPoint (void* userData)
{
static_cast <Thread*> (userData)->threadEntryPoint();
}
//==============================================================================
void Thread::startThread()
{
std::lock_guard<std::recursive_mutex> sl (startStopLock);
shouldExit = false;
if (threadHandle == nullptr)
{
launchThread();
startSuspensionEvent.signal();
}
}
bool Thread::isThreadRunning() const
{
return threadHandle != nullptr;
}
//==============================================================================
void Thread::signalThreadShouldExit()
{
shouldExit = true;
}
void Thread::waitForThreadToExit () const
{
while (isThreadRunning())
std::this_thread::sleep_for (std::chrono::milliseconds (10));
}
void Thread::stopThread ()
{
std::lock_guard<std::recursive_mutex> sl (startStopLock);
if (isThreadRunning())
{
signalThreadShouldExit();
notify();
waitForThreadToExit ();
}
}
void Thread::stopThreadAsync ()
{
std::lock_guard<std::recursive_mutex> sl (startStopLock);
if (isThreadRunning())
{
signalThreadShouldExit();
notify();
}
}
//==============================================================================
bool Thread::wait (const int timeOutMilliseconds) const
{
return defaultEvent.wait (timeOutMilliseconds);
}
void Thread::notify() const
{
defaultEvent.signal();
}
}
//------------------------------------------------------------------------------
#if BEAST_WINDOWS
#include <windows.h>
#include <process.h>
#include <tchar.h>
namespace beast {
HWND beast_messageWindowHandle = 0; // (this is used by other parts of the codebase)
void beast_threadEntryPoint (void*);
static unsigned int __stdcall threadEntryProc (void* userData)
{
if (beast_messageWindowHandle != 0)
AttachThreadInput (GetWindowThreadProcessId (beast_messageWindowHandle, 0),
GetCurrentThreadId(), TRUE);
beast_threadEntryPoint (userData);
_endthreadex (0);
return 0;
}
void Thread::launchThread()
{
unsigned int newThreadId;
threadHandle = (void*) _beginthreadex (0, 0, &threadEntryProc, this, 0, &newThreadId);
}
void Thread::closeThreadHandle()
{
CloseHandle ((HANDLE) threadHandle);
threadHandle = 0;
}
void Thread::setCurrentThreadName (std::string const& name)
{
#if BEAST_DEBUG && BEAST_MSVC
struct
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} info;
info.dwType = 0x1000;
info.szName = name.c_str ();
info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try
{
RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{}
#else
(void) name;
#endif
}
}
//------------------------------------------------------------------------------
#else
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#if BEAST_BSD
// ???
#elif BEAST_MAC || BEAST_IOS
#include <Foundation/NSThread.h>
#include <Foundation/NSString.h>
#import <objc/message.h>
namespace beast{
#include <ripple/beast/core/osx_ObjCHelpers.h>
}
#else
#include <sys/prctl.h>
#endif
namespace beast {
void beast_threadEntryPoint (void*);
extern "C" void* threadEntryProcBeast (void*);
extern "C" void* threadEntryProcBeast (void* userData)
{
BEAST_AUTORELEASEPOOL
{
#if BEAST_ANDROID
struct AndroidThreadScope
{
AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
};
const AndroidThreadScope androidEnv;
#endif
beast_threadEntryPoint (userData);
}
return nullptr;
}
void Thread::launchThread()
{
threadHandle = 0;
pthread_t handle = 0;
if (pthread_create (&handle, 0, threadEntryProcBeast, this) == 0)
{
pthread_detach (handle);
threadHandle = (void*) handle;
}
}
void Thread::closeThreadHandle()
{
threadHandle = 0;
}
void Thread::setCurrentThreadName (std::string const& name)
{
#if BEAST_IOS || (BEAST_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
BEAST_AUTORELEASEPOOL
{
[[NSThread currentThread] setName: stringToNS (name)];
}
#elif BEAST_LINUX
#if (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
pthread_setname_np (pthread_self(), name.c_str ());
#else
prctl (PR_SET_NAME, name.c_str (), 0, 0, 0);
#endif
#endif
}
}
//------------------------------------------------------------------------------
#endif

View File

@@ -1,187 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.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_THREADS_THREAD_H_INCLUDED
#define BEAST_THREADS_THREAD_H_INCLUDED
#include <ripple/beast/core/WaitableEvent.h>
#include <mutex>
#include <string>
namespace beast {
//==============================================================================
/**
Encapsulates a thread.
Subclasses derive from Thread and implement the run() method, in which they
do their business. The thread can then be started with the startThread() method
and controlled with various other methods.
@see WaitableEvent, Process, ThreadWithProgressWindow,
MessageManagerLock
*/
class Thread
{
public:
//==============================================================================
/**
Creates a thread.
When first created, the thread is not running. Use the startThread()
method to start it.
*/
explicit Thread (std::string const& threadName);
Thread (Thread const&) = delete;
Thread& operator= (Thread const&) = delete;
/** Destructor.
If the thread has not been stopped first, this will generate a fatal error.
*/
virtual ~Thread();
//==============================================================================
/** Must be implemented to perform the thread's actual code.
Remember that the thread must regularly check the threadShouldExit()
method whilst running, and if this returns true it should return from
the run() method as soon as possible to avoid being forcibly killed.
@see threadShouldExit, startThread
*/
virtual void run() = 0;
//==============================================================================
// Thread control functions..
/** Starts the thread running.
This will start the thread's run() method.
(if it's already started, startThread() won't do anything).
@see stopThread
*/
void startThread();
/** Attempts to stop the thread running.
This method will cause the threadShouldExit() method to return true
and call notify() in case the thread is currently waiting.
*/
void stopThread ();
/** Stop the thread without blocking.
This calls signalThreadShouldExit followed by notify.
*/
void stopThreadAsync ();
//==============================================================================
/** Returns true if the thread is currently active */
bool isThreadRunning() const;
/** Sets a flag to tell the thread it should stop.
Calling this means that the threadShouldExit() method will then return true.
The thread should be regularly checking this to see whether it should exit.
If your thread makes use of wait(), you might want to call notify() after calling
this method, to interrupt any waits that might be in progress, and allow it
to reach a point where it can exit.
@see threadShouldExit
@see waitForThreadToExit
*/
void signalThreadShouldExit();
/** Checks whether the thread has been told to stop running.
Threads need to check this regularly, and if it returns true, they should
return from their run() method at the first possible opportunity.
@see signalThreadShouldExit
*/
inline bool threadShouldExit() const { return shouldExit; }
/** Waits for the thread to stop.
This will waits until isThreadRunning() is false.
*/
void waitForThreadToExit () const;
//==============================================================================
/** Makes the thread wait for a notification.
This puts the thread to sleep until either the timeout period expires, or
another thread calls the notify() method to wake it up.
A negative time-out value means that the method will wait indefinitely.
@returns true if the event has been signalled, false if the timeout expires.
*/
bool wait (int timeOutMilliseconds = -1) const;
/** Wakes up the thread.
If the thread has called the wait() method, this will wake it up.
@see wait
*/
void notify() const;
//==============================================================================
/** Returns the name of the thread.
This is the name that gets set in the constructor.
*/
std::string const& getThreadName() const { return threadName; }
/** Changes the name of the caller thread.
Different OSes may place different length or content limits on this name.
*/
static void setCurrentThreadName (std::string const& newThreadName);
private:
//==============================================================================
std::string const threadName;
void* volatile threadHandle;
std::recursive_mutex startStopLock;
WaitableEvent startSuspensionEvent, defaultEvent;
bool volatile shouldExit;
#ifndef DOXYGEN
friend void beast_threadEntryPoint (void*);
#endif
void launchThread();
void closeThreadHandle();
void threadEntryPoint();
};
}
#endif

View File

@@ -190,9 +190,9 @@
#endif
#include <ripple/beast/core/CurrentThreadName.cpp>
#include <ripple/beast/core/SemanticVersion.cpp>
#include <ripple/beast/core/SystemStats.cpp>
#include <ripple/beast/core/Thread.cpp>
#include <ripple/beast/core/Time.cpp>
#include <ripple/beast/core/WaitableEvent.cpp>

View File

@@ -133,9 +133,6 @@ public:
bool operator<= (const Job& j) const;
bool operator>= (const Job& j) const;
private:
void doJobImpl();
private:
CancelCallback m_cancelCallback;
JobType mType;

View File

@@ -30,7 +30,6 @@
#include <ripple/basics/Log.h>
#include <ripple/core/JobQueue.h>
#include <ripple/beast/core/Thread.h>
#define SOCI_USE_BOOST
#include <soci/soci.h>
#include <string>

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Copyright (c) 2012 - 2017 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
@@ -17,13 +17,13 @@
*/
//==============================================================================
#ifndef RIPPLE_BASICS_THREADNAME_H_INCLUDED
#define RIPPLE_BASICS_THREADNAME_H_INCLUDED
#ifndef RIPPLE_CORE_TERMINATE_HANDLER_H_INCLUDED
#define RIPPLE_CORE_TERMINATE_HANDLER_H_INCLUDED
namespace ripple {
namespace ripple
{
// VFALCO This should use the beast function
extern void setCallingThreadName (char const*);
void terminateHandler();
} // ripple

View File

@@ -1,103 +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.
*/
//==============================================================================
#ifndef RIPPLE_CORE_THREAD_ENTRY_H_INCLUDED
#define RIPPLE_CORE_THREAD_ENTRY_H_INCLUDED
#include <string>
namespace ripple
{
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
namespace detail
{
void setThreadName(std::string name);
}
void terminateHandler();
#endif
/**
Report uncaught exceptions to DebugLog and cerr
The actual reporting occurs in a terminate handler. This function
stores information about which thread is running in thread local
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
many platforms the stack trace for an uncaught exception on a thread
is almost useless.
For those platforms where the stack trace from an uncaught exception is
useful (e.g., OS X) this routine is turned into a no-op (because the
preprocessor symbol NO_LOG_UNHANDLED_EXCEPTIONS is defined).
Usage example
#include <ripple/core/ThreadEntry.h>
#include <chrono>
#include <exception>
#include <thread>
class ThreadedHandler
{
public:
void operator() ()
{
threadEntry (
this, &ThreadedHandler::runImpl, "ThreadedHandler::operator()");
}
void runImpl()
{
// do stuff.
throw std::logic_error("logic_error: What was I thinking?");
}
};
int main ()
{
using namespace std::chrono_literals;
ThreadedHandler handler;
std::thread t {handler};
std::this_thread::sleep_for (1s);
t.join();
return 0;
}
@param t Pointer to object to call.
@param threadTop Pointer to member function of t to call.
@param name Name of function to log.
*/
template <typename T, typename R>
void threadEntry (
T* t, R (T::*threadTop) (), std::string name)
{
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
detail::setThreadName (std::move(name));
#endif
((t)->*(threadTop)) ();
}
} // namespace ripple
#endif

View File

@@ -19,8 +19,8 @@
#include <BeastConfig.h>
#include <ripple/core/DeadlineTimer.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/basics/contract.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <cassert>
#include <condition_variable>
#include <mutex>
@@ -132,14 +132,9 @@ public:
}
void run ()
{
threadEntry (
this, &Manager::runImpl, "DeadlineTimer::Manager::run()");
}
void runImpl ()
{
using namespace std::chrono;
beast::setCurrentThreadName ("DeadlineTimer");
bool shouldExit = true;
do

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/core/Job.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <cassert>
namespace ripple {
@@ -77,12 +77,15 @@ bool Job::shouldCancel () const
void Job::doJob ()
{
std::stringstream ss;
ss << "Job::doJob(); Job name: "
<< mName << "; Job type: " << mType
<< "; Job info: " << mJob.target_type ().name ();
beast::setCurrentThreadName ("doJob: " + mName);
m_loadEvent->start ();
m_loadEvent->reName (mName);
threadEntry (this, &Job::doJobImpl, ss.str());
mJob (*this);
// Destroy the lambda, otherwise we won't include
// its duration in the time measurement
mJob = nullptr;
}
void Job::rename (std::string const& newName)
@@ -134,16 +137,4 @@ bool Job::operator<= (const Job& j) const
return mJobIndex <= j.mJobIndex;
}
void Job::doJobImpl ()
{
m_loadEvent->start ();
m_loadEvent->reName (mName);
mJob (*this);
// Destroy the lambda, otherwise we won't include
// its duration in the time measurement
mJob = std::function<void(Job&)>();
}
}

View File

@@ -461,7 +461,6 @@ JobQueue::processTask ()
}
type = job.getType();
JobTypeData& data(getJobTypeData(type));
beast::Thread::setCurrentThreadName (data.name ());
JLOG(m_journal.trace()) << "Doing " << data.name () << " job";
on_dequeue (job.getType (), start_time - job.queue_time ());
job.doJob ();

View File

@@ -20,10 +20,8 @@
#include <BeastConfig.h>
#include <ripple/core/impl/SNTPClock.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/ThreadName.h>
#include <ripple/basics/random.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <beast/core/placeholders.hpp>
#include <boost/asio.hpp>
#include <boost/optional.hpp>
@@ -203,13 +201,8 @@ public:
void doRun ()
{
setCallingThreadName("SNTPClock");
// Get the address of an overloaded asio method
using Pio_service_mem = std::size_t (boost::asio::io_service::*)();
Pio_service_mem pRun = &boost::asio::io_service::run;
threadEntry (&io_service_, pRun, "SNTPClientImp::doRun()");
beast::setCurrentThreadName("rippled: SNTPClock");
io_service_.run();
}
void

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Copyright (c) 2012 - 2017 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
@@ -18,61 +18,52 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/core/TerminateHandler.h>
#include <ripple/basics/Log.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <boost/coroutine/exceptions.hpp>
#include <boost/thread/tss.hpp>
#include <exception>
#include <iostream>
#include <typeinfo>
namespace ripple {
#ifndef NO_LOG_UNHANDLED_EXCEPTIONS
static boost::thread_specific_ptr<std::string> threadName;
namespace detail {
void setThreadName(std::string name)
{
try
{
threadName.reset(new std::string{std::move(name)});
}
catch(...)
{
}
}
}
void terminateHandler()
{
if (std::current_exception())
{
std::string const name = threadName.get() ? *threadName.get() : "Unknown";
auto const thName =
beast::getCurrentThreadName().value_or("Unknown");
try
{
throw;
}
catch (const std::exception& e)
{
std::cerr << name << ": " << e.what () << '\n';
auto exName = typeid (e).name();
std::cerr
<< "Terminating thread " << thName << ": unhandled "
<< exName << " '" << e.what () << "'\n";
JLOG(debugLog().fatal())
<< name << ": " << e.what () << '\n';
<< "Terminating thread " << thName << ": unhandled "
<< exName << " '" << e.what () << "'\n";
}
catch (boost::coroutines::detail::forced_unwind const&)
{
std::cerr << name << ": forced_unwind\n";
std::cerr
<< "Terminating thread " << thName << ": forced_unwind\n";
JLOG(debugLog().fatal())
<< name << ": forced_unwind\n";
<< "Terminating thread " << thName << ": forced_unwind\n";
}
catch (...)
{
std::cerr << name << ": unknown exception\n";
JLOG (debugLog ().fatal ())
<< name << ": unknown exception\n";
std::cerr
<< "Terminating thread " << thName << ": unknown exception\n";
JLOG (debugLog().fatal())
<< "Terminating thread " << thName << ": unknown exception\n";
}
}
}
#endif
}

View File

@@ -18,7 +18,7 @@
//==============================================================================
#include <ripple/core/impl/Workers.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <cassert>
namespace ripple {
@@ -170,18 +170,7 @@ void Workers::Worker::notify ()
wakeup_.notify_one();
}
static void setInactiveThreadName (std::string const& threadName)
{
beast::Thread::setCurrentThreadName ("(" + threadName + ")");
}
void Workers::Worker::run ()
{
setInactiveThreadName (threadName_);
threadEntry (this, &Workers::Worker::runImpl, threadName_);
}
void Workers::Worker::runImpl ()
{
bool shouldExit = true;
do
@@ -194,6 +183,9 @@ void Workers::Worker::runImpl ()
for (;;)
{
// Put the name back in case the callback changed it
beast::setCurrentThreadName (threadName_);
// Acquire a task or "internal task."
//
m_workers.m_semaphore.wait ();
@@ -226,9 +218,6 @@ void Workers::Worker::runImpl ()
++m_workers.m_runningTaskCount;
m_workers.m_callback.processTask ();
--m_workers.m_runningTaskCount;
// Put the name back in case the callback changed it
beast::Thread::setCurrentThreadName (threadName_);
}
// Any worker that goes into the paused list must
@@ -243,7 +232,8 @@ void Workers::Worker::runImpl ()
if (--m_workers.m_activeCount == 0)
m_workers.m_allPaused.signal ();
setInactiveThreadName (threadName_);
// Set inactive thread name.
beast::setCurrentThreadName ("(" + threadName_ + ")");
// [1] We will be here when the paused list is popped
//

View File

@@ -21,8 +21,8 @@
#define RIPPLE_CORE_WORKERS_H_INCLUDED
#include <ripple/core/impl/semaphore.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/beast/core/LockFreeStack.h>
#include <ripple/beast/core/WaitableEvent.h>
#include <atomic>
#include <condition_variable>
#include <mutex>
@@ -131,7 +131,6 @@ private:
private:
void run ();
void runImpl ();
private:
Workers& m_workers;

View File

@@ -30,7 +30,7 @@
#include <ripple/nodestore/impl/BatchWriter.h>
#include <ripple/nodestore/impl/DecodedBlob.h>
#include <ripple/nodestore/impl/EncodedBlob.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <atomic>
#include <memory>
@@ -70,7 +70,7 @@ public:
std::size_t const id (++n);
std::stringstream ss;
ss << "rocksdb #" << id;
beast::Thread::setCurrentThreadName (ss.str());
beast::setCurrentThreadName (ss.str());
(*f)(a);
}

View File

@@ -29,7 +29,7 @@
#include <ripple/nodestore/Manager.h>
#include <ripple/nodestore/impl/DecodedBlob.h>
#include <ripple/nodestore/impl/EncodedBlob.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <atomic>
#include <memory>
@@ -69,7 +69,7 @@ public:
std::size_t const id (++n);
std::stringstream ss;
ss << "rocksdb #" << id;
beast::Thread::setCurrentThreadName (ss.str());
beast::setCurrentThreadName (ss.str());
(*f)(a);
}

View File

@@ -26,11 +26,10 @@
#include <ripple/basics/KeyCache.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/chrono.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/protocol/digest.h>
#include <ripple/basics/Slice.h>
#include <ripple/basics/TaggedCache.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <chrono>
#include <condition_variable>
#include <set>
@@ -335,17 +334,10 @@ public:
//------------------------------------------------------------------------------
// Uncaught exception handling for async read threads
// Entry point for async read threads
void threadEntry ()
{
::ripple::threadEntry (
this, &DatabaseImp::threadEntryImpl, "DatabaseImp::threadEntry()");
}
// Entry point for async read threads
void threadEntryImpl ()
{
beast::Thread::setCurrentThreadName ("prefetch");
beast::setCurrentThreadName ("prefetch");
while (1)
{
uint256 hash;

View File

@@ -22,8 +22,7 @@
#include <ripple/resource/impl/Logic.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/Log.h>
#include <ripple/core/ThreadEntry.h>
#include <ripple/beast/core/Thread.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <condition_variable>
#include <memory>
#include <mutex>
@@ -114,13 +113,7 @@ public:
private:
void run ()
{
threadEntry (
this, &ManagerImp::runImpl, "Resource::Manager::run()");
}
void runImpl ()
{
beast::Thread::setCurrentThreadName ("Resource::Manager");
beast::setCurrentThreadName ("Resource::Manager");
for(;;)
{
logic_.periodicActivity();

View File

@@ -25,7 +25,6 @@
#include <ripple/server/impl/Door.h>
#include <ripple/server/impl/io_list.h>
#include <ripple/beast/core/List.h>
#include <ripple/beast/core/Thread.h>
#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <array>
@@ -99,7 +98,7 @@ private:
std::vector<std::weak_ptr<Door<Handler>>> list_;
int high_ = 0;
std::array <std::size_t, 64> hist_;
io_list ios_;
public:

View File

@@ -31,7 +31,6 @@
#include <ripple/basics/impl/strHex.cpp>
#include <ripple/basics/impl/StringUtilities.cpp>
#include <ripple/basics/impl/Sustain.cpp>
#include <ripple/basics/impl/ThreadName.cpp>
#include <ripple/basics/impl/Time.cpp>
#include <ripple/basics/impl/UptimeTimer.cpp>

View File

@@ -28,7 +28,7 @@
#include <ripple/core/impl/JobQueue.cpp>
#include <ripple/core/impl/SNTPClock.cpp>
#include <ripple/core/impl/Stoppable.cpp>
#include <ripple/core/impl/TerminateHandler.cpp>
#include <ripple/core/impl/TimeKeeper.cpp>
#include <ripple/core/impl/ThreadEntry.cpp>
#include <ripple/core/impl/Workers.cpp>

View File

@@ -0,0 +1,88 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2017 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/beast/core/CurrentThreadName.h>
#include <ripple/beast/unit_test.h>
#include <atomic>
#include <thread>
namespace ripple {
namespace test {
class CurrentThreadName_test : public beast::unit_test::suite
{
private:
static void exerciseName (
std::string myName, std::atomic<bool>* stop, std::atomic<int>* state)
{
// Verify that upon creation a thread has no name.
auto const initialThreadName = beast::getCurrentThreadName();
// Set the new name.
beast::setCurrentThreadName (myName);
// Indicate to caller that the name is set.
*state = 1;
// If there is an initial thread name then we failed.
if (initialThreadName)
return;
// Wait until all threads have their names.
while (! *stop);
// Make sure the thread name that we set before is still there
// (not overwritten by, for instance, another thread).
if (beast::getCurrentThreadName() == myName)
*state = 2;
}
public:
void
run() override
{
// Make two different threads with two different names. Make sure
// that the expected thread names are still there when the thread
// exits.
std::atomic<bool> stop {false};
std::atomic<int> stateA {0};
std::thread tA (exerciseName, "tA", &stop, &stateA);
std::atomic<int> stateB {0};
std::thread tB (exerciseName, "tB", &stop, &stateB);
// Wait until both threads have set their names.
while (stateA == 0 || stateB == 0);
stop = true;
tA.join();
tB.join();
// Both threads should still have the expected name when they exit.
BEAST_EXPECT (stateA == 2);
BEAST_EXPECT (stateB == 2);
}
};
BEAST_DEFINE_TESTSUITE(CurrentThreadName,core,beast);
} // test
} // ripple

View File

@@ -0,0 +1,153 @@
//------------------------------------------------------------------------------
/*
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/core/TerminateHandler.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <ripple/beast/unit_test.h>
#include <boost/coroutine/exceptions.hpp>
#include <exception>
#include <sstream>
#include <streambuf>
namespace ripple {
namespace test {
class TerminateHandler_test : public beast::unit_test::suite
{
private:
// Allow cerr to be redirected. Destructor restores old cerr streambuf.
class CerrRedirect
{
public:
CerrRedirect (std::stringstream& sStream)
: old_ (std::cerr.rdbuf (sStream.rdbuf()))
{ }
~CerrRedirect()
{
std::cerr.rdbuf (old_);
}
private:
std::streambuf* const old_;
};
// Set a new current thread name. Destructor restores the old thread name.
class ThreadNameGuard
{
public:
ThreadNameGuard (std::string const& newName)
: old_ (beast::getCurrentThreadName ())
{
beast::setCurrentThreadName (newName);
}
~ThreadNameGuard()
{
std::string oldName;
if (old_)
oldName = std::move (*old_);
beast::setCurrentThreadName (oldName);
}
private:
boost::optional<std::string> old_;
};
public:
void
run() override
{
// Set the current thread name, but restore the old name on exit.
std::string const threadName {"terminateHandler_test"};
ThreadNameGuard nameGuard {threadName};
{
// Test terminateHandler() with a std::exception.
// The terminateHandler() output goes to std::cerr. Capture that.
std::stringstream cerrCapture;
CerrRedirect cerrRedirect {cerrCapture};
try
{
throw std::range_error ("Out of range");
}
catch (...)
{
terminateHandler();
}
{
std::string result = cerrCapture.str();
BEAST_EXPECT (result.find (threadName) != std::string::npos);
BEAST_EXPECT (
result.find ("Out of range") != std::string::npos);
}
}
{
// Verify terminateHnadler() handles forced_unwind correctly.
std::stringstream cerrCapture;
CerrRedirect cerrRedirect {cerrCapture};
try
{
throw boost::coroutines::detail::forced_unwind();
}
catch (...)
{
terminateHandler();
}
{
std::string result = cerrCapture.str();
BEAST_EXPECT (result.find (threadName) != std::string::npos);
BEAST_EXPECT (
result.find ("forced_unwind") != std::string::npos);
}
}
{
// Verify terminatHandler()'s handling of non-standard exceptions.
std::stringstream cerrCapture;
CerrRedirect cerrRedirect {cerrCapture};
try
{
throw 7;
}
catch (...)
{
terminateHandler();
}
{
std::string result = cerrCapture.str();
BEAST_EXPECT (result.find (threadName) != std::string::npos);
BEAST_EXPECT (
result.find ("unknown exception") != std::string::npos);
}
}
}
};
BEAST_DEFINE_TESTSUITE(TerminateHandler,core,ripple);
} // test
} // ripple

View File

@@ -19,13 +19,13 @@
#include <BeastConfig.h>
#include <ripple/basics/make_SSLContext.h>
#include <beast/core/placeholders.hpp>
#include <ripple/beast/core/CurrentThreadName.h>
#include <ripple/beast/unit_test.h>
#include <beast/core/placeholders.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
#include <ripple/beast/core/Thread.h>
#include <cassert>
#include <condition_variable>
#include <functional>
@@ -552,7 +552,7 @@ public:
: work_(boost::in_place(std::ref(io_service_)))
, thread_(std::thread([this]()
{
beast::Thread::setCurrentThreadName("io_service");
beast::setCurrentThreadName("io_service");
this->io_service_.run();
}))
, context_(make_SSLContext(""))

View File

@@ -22,6 +22,7 @@
#include <test/beast/beast_abstract_clock_test.cpp>
#include <test/beast/beast_asio_error_test.cpp>
#include <test/beast/beast_basic_seconds_clock_test.cpp>
#include <test/beast/beast_CurrentThreadName_test.cpp>
#include <test/beast/beast_Debug_test.cpp>
#include <test/beast/beast_Journal_test.cpp>
#include <test/beast/beast_PropertyStream_test.cpp>

View File

@@ -23,4 +23,5 @@
#include <test/core/DeadlineTimer_test.cpp>
#include <test/core/SociDB_test.cpp>
#include <test/core/Stoppable_test.cpp>
#include <test/core/TerminateHandler_test.cpp>
#include <test/core/Workers_test.cpp>