diff options
author | Gabriel Russell <gabriel.russell@mongodb.com> | 2020-11-18 14:22:26 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-11-23 16:02:49 +0000 |
commit | 71fb74aab300a852761e0ae3b0782c207f4aef52 (patch) | |
tree | 0fe6378967d350af497efdf7811b07de41a5cb18 | |
parent | f39eb409f4f3e32b3d77b4b05bb977113c52f48c (diff) | |
download | mongo-71fb74aab300a852761e0ae3b0782c207f4aef52.tar.gz |
SERVER-48696 sigaction actions need to all be extern "C"
-rw-r--r-- | src/mongo/shell/mongo_main.cpp | 2 | ||||
-rw-r--r-- | src/mongo/stdx/sigaltstack_location_test.cpp | 44 | ||||
-rw-r--r-- | src/mongo/util/debugger.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/signal_handlers_synchronous.cpp | 12 | ||||
-rw-r--r-- | src/mongo/util/stacktrace_test.cpp | 32 | ||||
-rw-r--r-- | src/mongo/util/stacktrace_threads.cpp | 5 |
6 files changed, 63 insertions, 36 deletions
diff --git a/src/mongo/shell/mongo_main.cpp b/src/mongo/shell/mongo_main.cpp index 4a4069077f7..6d0ff876265 100644 --- a/src/mongo/shell/mongo_main.cpp +++ b/src/mongo/shell/mongo_main.cpp @@ -304,7 +304,7 @@ void killOps() { !shellGlobalParams.autoKillOp); } -void quitNicely(int sig) { +extern "C" void quitNicely(int sig) { shutdown(EXIT_CLEAN); } diff --git a/src/mongo/stdx/sigaltstack_location_test.cpp b/src/mongo/stdx/sigaltstack_location_test.cpp index bfc0aba4393..e2d1d59fd36 100644 --- a/src/mongo/stdx/sigaltstack_location_test.cpp +++ b/src/mongo/stdx/sigaltstack_location_test.cpp @@ -69,8 +69,10 @@ void unblockSignal(int sig) { } } +extern "C" typedef void(sigAction_t)(int signum, siginfo_t* info, void* context); + /** Install action for signal sig. Be careful to specify SA_ONSTACK. */ -void installAction(int sig, void (*action)(int, siginfo_t*, void*)) { +void installAction(int sig, sigAction_t* action) { struct sigaction sa; sa.sa_sigaction = action; sa.sa_flags = SA_SIGINFO | SA_ONSTACK; @@ -100,39 +102,42 @@ struct Hex { const T& _t; }; +struct StackLocationTestChildThreadInfo { + stack_t ss; + const char* handlerLocal; +}; +static StackLocationTestChildThreadInfo stackLocationTestChildInfo{}; + +extern "C" void stackLocationTestAction(int, siginfo_t*, void*) { + char n; + stackLocationTestChildInfo.handlerLocal = &n; +} + int stackLocationTest() { - struct ChildThreadInfo { - stack_t ss; - const char* handlerLocal; - }; - static ChildThreadInfo childInfo{}; stdx::thread childThread([&] { static const int kSignal = SIGUSR1; // Use sigaltstack's `old_ss` parameter to query the installed sigaltstack. - if (sigaltstack(nullptr, &childInfo.ss)) { + if (sigaltstack(nullptr, &stackLocationTestChildInfo.ss)) { perror("sigaltstack"); abort(); } unblockSignal(kSignal); - installAction(kSignal, [](int, siginfo_t*, void*) { - char n; - childInfo.handlerLocal = &n; - }); + installAction(kSignal, &stackLocationTestAction); // `raise` waits for signal handler to complete. // https://pubs.opengroup.org/onlinepubs/009695399/functions/raise.html raise(kSignal); }); childThread.join(); - if (childInfo.ss.ss_flags & SS_DISABLE) { + if (stackLocationTestChildInfo.ss.ss_flags & SS_DISABLE) { std::cerr << "Child thread unexpectedly had sigaltstack disabled." << std::endl; exit(EXIT_FAILURE); } - uintptr_t altStackBegin = reinterpret_cast<uintptr_t>(childInfo.ss.ss_sp); - uintptr_t altStackEnd = altStackBegin + childInfo.ss.ss_size; - uintptr_t handlerLocal = reinterpret_cast<uintptr_t>(childInfo.handlerLocal); + uintptr_t altStackBegin = reinterpret_cast<uintptr_t>(stackLocationTestChildInfo.ss.ss_sp); + uintptr_t altStackEnd = altStackBegin + stackLocationTestChildInfo.ss.ss_size; + uintptr_t handlerLocal = reinterpret_cast<uintptr_t>(stackLocationTestChildInfo.handlerLocal); std::cerr << "child sigaltstack[" << Hex(altStackEnd - altStackBegin) << "] = [" << Hex(altStackBegin) << ", " << Hex(altStackEnd) << ")\n" @@ -146,6 +151,12 @@ int stackLocationTest() { return EXIT_SUCCESS; } +static sigjmp_buf sigjmp; + +extern "C" void siglongjmpAction(int, siginfo_t*, void*) { + siglongjmp(sigjmp, 1); +} + /** * Start a child thread which overflows its stack, causing it to receive a SIGSEGV. If * !useSigAltStack, disable that child thread's sigaltstack. @@ -160,10 +171,9 @@ int stackLocationTest() { * SIGSEGV is process-fatal. */ int recursionTestImpl(bool useSigAltStack) { - static sigjmp_buf sigjmp; unblockSignal(SIGSEGV); - installAction(SIGSEGV, [](int, siginfo_t*, void*) { siglongjmp(sigjmp, 1); }); + installAction(SIGSEGV, siglongjmpAction); stdx::thread childThread([=] { if (!useSigAltStack) { diff --git a/src/mongo/util/debugger.cpp b/src/mongo/util/debugger.cpp index c4a89d0bdc2..3bd216f1656 100644 --- a/src/mongo/util/debugger.cpp +++ b/src/mongo/util/debugger.cpp @@ -117,7 +117,7 @@ void launchDebugger(Exec debugger) { #if defined(USE_GDBSERVER) -void execCallback(int) { +extern "C" void execCallback(int) { launchDebugger([](char* pidToDebug) { execlp("gdbserver", "gdbserver", "--attach", ":0", pidToDebug, nullptr); }); @@ -125,7 +125,7 @@ void execCallback(int) { #elif defined(USE_LLDB_SERVER) -void execCallback(int) { +extern "C" void execCallback(int) { launchDebugger([](char* pidToDebug) { #ifdef __linux__ execlp("lldb-server", "lldb-server", "g", "--attach", pidToDebug, "*:12345", nullptr); diff --git a/src/mongo/util/signal_handlers_synchronous.cpp b/src/mongo/util/signal_handlers_synchronous.cpp index 7a1d2261bee..dbb2caacb4f 100644 --- a/src/mongo/util/signal_handlers_synchronous.cpp +++ b/src/mongo/util/signal_handlers_synchronous.cpp @@ -257,7 +257,7 @@ void myTerminate() { endProcessWithSignal(SIGABRT); } -void abruptQuit(int signalNum) { +extern "C" void abruptQuit(int signalNum) { MallocFreeOStreamGuard lk{}; printSignalAndBacktrace(signalNum); breakpoint(); @@ -292,11 +292,11 @@ void myPureCallHandler() { #else -void abruptQuitAction(int signalNum, siginfo_t*, void*) { +extern "C" void abruptQuitAction(int signalNum, siginfo_t*, void*) { abruptQuit(signalNum); }; -void abruptQuitWithAddrSignal(int signalNum, siginfo_t* siginfo, void* ucontext_erased) { +extern "C" void abruptQuitWithAddrSignal(int signalNum, siginfo_t* siginfo, void* ucontext_erased) { // For convenient debugger access. MONGO_COMPILER_VARIABLE_UNUSED auto ucontext = static_cast<const ucontext_t*>(ucontext_erased); @@ -319,6 +319,10 @@ void abruptQuitWithAddrSignal(int signalNum, siginfo_t* siginfo, void* ucontext_ } // namespace +#if !defined(_WIN32) +extern "C" typedef void(sigAction_t)(int signum, siginfo_t* info, void* context); +#endif + void setupSynchronousSignalHandlers() { stdx::set_terminate(myTerminate); std::set_new_handler(reportOutOfMemoryErrorAndExit); @@ -331,7 +335,7 @@ void setupSynchronousSignalHandlers() { #else static constexpr struct { int signal; - void (*function)(int, siginfo_t*, void*); // signal ignored if nullptr + sigAction_t* function; // signal ignored if nullptr } kSignalSpecs[] = { {SIGHUP, nullptr}, {SIGUSR2, nullptr}, diff --git a/src/mongo/util/stacktrace_test.cpp b/src/mongo/util/stacktrace_test.cpp index 9bf6dd99a19..cb06e5e8ef8 100644 --- a/src/mongo/util/stacktrace_test.cpp +++ b/src/mongo/util/stacktrace_test.cpp @@ -377,6 +377,8 @@ TEST(StackTrace, MetadataGeneratorFunctionMeasure) { #endif // _WIN32 #ifdef HAVE_SIGALTSTACK +extern "C" typedef void(sigAction_t)(int signum, siginfo_t* info, void* context); + class StackTraceSigAltStackTest : public unittest::Test { public: using unittest::Test::Test; @@ -398,7 +400,7 @@ public: 23388, "Local var", "var"_attr = "{:X}"_format(reinterpret_cast<uintptr_t>(&storage))); } - static void tryHandler(void (*handler)(int, siginfo_t*, void*)) { + static void tryHandler(sigAction_t* handler) { constexpr int sig = SIGUSR1; constexpr size_t kStackSize = size_t{1} << 20; // 1 MiB auto buf = std::make_unique<std::array<unsigned char, kStackSize>>(); @@ -447,23 +449,31 @@ public: } }; +extern "C" void stackTraceSigAltStackMinimalAction(int sig, siginfo_t*, void*) { + StackTraceSigAltStackTest::handlerPreamble(sig); +} + TEST_F(StackTraceSigAltStackTest, Minimal) { - tryHandler([](int sig, siginfo_t*, void*) { handlerPreamble(sig); }); + StackTraceSigAltStackTest::tryHandler(stackTraceSigAltStackMinimalAction); +} + +extern "C" void stackTraceSigAltStackPrintAction(int sig, siginfo_t*, void*) { + StackTraceSigAltStackTest::handlerPreamble(sig); + printStackTrace(); } TEST_F(StackTraceSigAltStackTest, Print) { - tryHandler([](int sig, siginfo_t*, void*) { - handlerPreamble(sig); - printStackTrace(); - }); + StackTraceSigAltStackTest::tryHandler(&stackTraceSigAltStackPrintAction); +} + +extern "C" void stackTraceSigAltStackBacktraceAction(int sig, siginfo_t*, void*) { + StackTraceSigAltStackTest::handlerPreamble(sig); + std::array<void*, kStackTraceFrameMax> addrs; + rawBacktrace(addrs.data(), addrs.size()); } TEST_F(StackTraceSigAltStackTest, Backtrace) { - tryHandler([](int sig, siginfo_t*, void*) { - handlerPreamble(sig); - std::array<void*, kStackTraceFrameMax> addrs; - rawBacktrace(addrs.data(), addrs.size()); - }); + StackTraceSigAltStackTest::tryHandler(stackTraceSigAltStackBacktraceAction); } #endif // HAVE_SIGALTSTACK diff --git a/src/mongo/util/stacktrace_threads.cpp b/src/mongo/util/stacktrace_threads.cpp index 62a5b020a2c..d2ee29d24b4 100644 --- a/src/mongo/util/stacktrace_threads.cpp +++ b/src/mongo/util/stacktrace_threads.cpp @@ -638,6 +638,9 @@ void State::action(siginfo_t* si) { } State* stateSingleton = new State{}; +extern "C" void stateSingletonAction(int, siginfo_t* si, void*) { + stateSingleton->action(si); +} /** * Called from single-thread init time. The stack tracer will use the specified `signal`. @@ -650,7 +653,7 @@ void initialize(int signal) { // We should never need to add to this lambda because it simply sets up handler // execution. Any changes should either be in State::action or in the signal // handler itself. - sa.sa_sigaction = [](int, siginfo_t* si, void*) { stateSingleton->action(si); }; + sa.sa_sigaction = stateSingletonAction; sa.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; if (sigaction(signal, &sa, nullptr) != 0) { int savedErr = errno; |