summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Russell <gabriel.russell@mongodb.com>2020-11-18 14:22:26 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-11-23 16:02:49 +0000
commit71fb74aab300a852761e0ae3b0782c207f4aef52 (patch)
tree0fe6378967d350af497efdf7811b07de41a5cb18
parentf39eb409f4f3e32b3d77b4b05bb977113c52f48c (diff)
downloadmongo-71fb74aab300a852761e0ae3b0782c207f4aef52.tar.gz
SERVER-48696 sigaction actions need to all be extern "C"
-rw-r--r--src/mongo/shell/mongo_main.cpp2
-rw-r--r--src/mongo/stdx/sigaltstack_location_test.cpp44
-rw-r--r--src/mongo/util/debugger.cpp4
-rw-r--r--src/mongo/util/signal_handlers_synchronous.cpp12
-rw-r--r--src/mongo/util/stacktrace_test.cpp32
-rw-r--r--src/mongo/util/stacktrace_threads.cpp5
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;