From d1e71e22fe0d89e8b83c5514506b00e7dfdbdef3 Mon Sep 17 00:00:00 2001 From: Andrew Morrow Date: Fri, 4 Apr 2014 17:08:49 -0400 Subject: [PATCH] CXX-151 As part of RC3 backport, drop signal_handlers. These files changed significantly between rc2 and rc3, including pulling in a new dependency on db/client.h, which we had not extracted. We def. don't want db/client.h and its transitive dependencies, but as a nice consequence of other edits in rc2..rc3, no files that we own now depend on signal_handlers.h, so we can drop the dependency, rather than needing to pull in db/client.h Note that we have already made this change on the legacy branch. The driver library shouldn't be in the business of signal handling. --- src/SConscript.client | 2 - src/mongo/util/signal_handlers.cpp | 276 ----------------------------- src/mongo/util/signal_handlers.h | 37 ---- 3 files changed, 315 deletions(-) delete mode 100644 src/mongo/util/signal_handlers.cpp delete mode 100644 src/mongo/util/signal_handlers.h diff --git a/src/SConscript.client b/src/SConscript.client index dd11a9fd40..c8e210a39b 100644 --- a/src/SConscript.client +++ b/src/SConscript.client @@ -98,7 +98,6 @@ clientSourceBasic = [ 'mongo/util/net/sock.cpp', "mongo/util/net/socket_poll.cpp", 'mongo/util/net/ssl_manager.cpp', - 'mongo/util/signal_handlers.cpp', 'mongo/util/stringutils.cpp', 'mongo/util/text.cpp', 'mongo/util/time_support.cpp', @@ -231,7 +230,6 @@ clientHeaders = [ 'mongo/util/net/sock.h', 'mongo/util/net/ssl_manager.h', 'mongo/util/net/ssl_options.h', - 'mongo/util/signal_handlers.h', 'mongo/util/time_support.h', 'mongo/util/version.h', ] diff --git a/src/mongo/util/signal_handlers.cpp b/src/mongo/util/signal_handlers.cpp deleted file mode 100644 index 766168b769..0000000000 --- a/src/mongo/util/signal_handlers.cpp +++ /dev/null @@ -1,276 +0,0 @@ -// signal_handlers.cpp - -/* Copyright 2014 MongoDB Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/util/signal_handlers.h" - -#include - -#include "mongo/db/client.h" -#include "mongo/db/log_process_details.h" -#include "mongo/util/assert_util.h" -#include "mongo/util/exit_code.h" -#include "mongo/util/log.h" -#include "mongo/util/scopeguard.h" -#include "mongo/util/stacktrace.h" - -#if defined(_WIN32) -# include "mongo/util/signal_win32.h" -# include "mongo/util/exception_filter_win32.h" -#else -# include -# include -#endif - -#if defined(_WIN32) -namespace { - const char* strsignal(int signalNum) { - // should only see SIGABRT on windows - switch (signalNum) { - case SIGABRT: return "SIGABRT"; - default: return "UNKNOWN"; - } - } -} -#endif - -namespace mongo { - - /* - * WARNING: PLEASE READ BEFORE CHANGING THIS MODULE - * - * All code in this module must be signal-friendly. Before adding any system - * call or other dependency, please make sure that this still holds. - * - * All code in this file follows this pattern: - * Generic code - * #ifdef _WIN32 - * Windows code - * #else - * Posix code - * #endif - * - */ - - // everything provides this, but only header is instance.h - void exitCleanly(ExitCode exitCode); - -namespace { - - // this will be called in certain c++ error cases, for example if there are two active - // exceptions - void myTerminate() { - printStackTrace(severe().stream() - << "terminate() called, printing stack (if implemented for platform):\n"); - ::_exit(EXIT_ABRUPT); - } - - // this gets called when new fails to allocate memory - void myNewHandler() { - printStackTrace(severe().stream() << "out of memory, printing stack and exiting:\n"); - ::_exit(EXIT_ABRUPT); - } - - void abruptQuit(int signalNum) { - { - LogstreamBuilder logBuilder = severe(); - logBuilder << - "Got signal: " << signalNum << " (" << strsignal(signalNum) << ").\nBacktrace:"; - printStackTrace(logBuilder.stream()); - } - - // Don't go through normal shutdown procedure. It may make things worse. - ::_exit(EXIT_ABRUPT); - } - -#ifdef _WIN32 - - void consoleTerminate( const char* controlCodeName ) { - Client::initThread( "consoleTerminate" ); - log() << "got " << controlCodeName << ", will terminate after current cmd ends" << endl; - exitCleanly( EXIT_KILL ); - } - - BOOL WINAPI CtrlHandler( DWORD fdwCtrlType ) { - - switch( fdwCtrlType ) { - - case CTRL_C_EVENT: - log() << "Ctrl-C signal"; - consoleTerminate( "CTRL_C_EVENT" ); - return TRUE ; - - case CTRL_CLOSE_EVENT: - log() << "CTRL_CLOSE_EVENT signal"; - consoleTerminate( "CTRL_CLOSE_EVENT" ); - return TRUE ; - - case CTRL_BREAK_EVENT: - log() << "CTRL_BREAK_EVENT signal"; - consoleTerminate( "CTRL_BREAK_EVENT" ); - return TRUE; - - case CTRL_LOGOFF_EVENT: - // only sent to services, and only in pre-Vista Windows; FALSE means ignore - return FALSE; - - case CTRL_SHUTDOWN_EVENT: - log() << "CTRL_SHUTDOWN_EVENT signal"; - consoleTerminate( "CTRL_SHUTDOWN_EVENT" ); - return TRUE; - - default: - return FALSE; - } - } - - void eventProcessingThread() { - std::string eventName = getShutdownSignalName(ProcessId::getCurrent().asUInt32()); - - HANDLE event = CreateEventA(NULL, TRUE, FALSE, eventName.c_str()); - if (event == NULL) { - warning() << "eventProcessingThread CreateEvent failed: " - << errnoWithDescription(); - return; - } - - ON_BLOCK_EXIT(CloseHandle, event); - - int returnCode = WaitForSingleObject(event, INFINITE); - if (returnCode != WAIT_OBJECT_0) { - if (returnCode == WAIT_FAILED) { - warning() << "eventProcessingThread WaitForSingleObject failed: " - << errnoWithDescription(); - return; - } - else { - warning() << "eventProcessingThread WaitForSingleObject failed: " - << errnoWithDescription(returnCode); - return; - } - } - - Client::initThread("eventTerminate"); - log() << "shutdown event signaled, will terminate after current cmd ends"; - exitCleanly(EXIT_CLEAN); - } - -#else - - void abruptQuitWithAddrSignal( int signalNum, siginfo_t *siginfo, void * ) { - { - LogstreamBuilder logBuilder = severe(); - - logBuilder << "Invalid"; - if ( signalNum == SIGSEGV || signalNum == SIGBUS ) { - logBuilder << " access"; - } else { - logBuilder << " operation"; - } - logBuilder << " at address: " << siginfo->si_addr; - } - abruptQuit( signalNum ); - } - - // The signals in asyncSignals will be processed by this thread only, in order to - // ensure the db and log mutexes aren't held. - sigset_t asyncSignals; - void signalProcessingThread() { - Client::initThread( "signalProcessingThread" ); - while (true) { - int actualSignal = 0; - int status = sigwait( &asyncSignals, &actualSignal ); - fassert(16781, status == 0); - switch (actualSignal) { - case SIGUSR1: - // log rotate signal - fassert(16782, rotateLogs()); - logProcessDetailsForLogRotate(); - break; - case SIGQUIT: - log() << "Received SIGQUIT; terminating."; - _exit(EXIT_ABRUPT); - default: - // interrupt/terminate signal - log() << "got signal " << actualSignal << " (" << strsignal( actualSignal ) - << "), will terminate after current cmd ends" << endl; - exitCleanly( EXIT_CLEAN ); - break; - } - } - } -#endif -} // namespace - - void setupSignalHandlers() { - set_terminate( myTerminate ); - set_new_handler( myNewHandler ); - - // SIGABRT is the only signal we want handled by signal handlers on both windows and posix. - invariant( signal(SIGABRT, abruptQuit) != SIG_ERR ); - -#ifdef _WIN32 - _set_purecall_handler( ::abort ); // TODO improve? - setWindowsUnhandledExceptionFilter(); - massert(10297, - "Couldn't register Windows Ctrl-C handler", - SetConsoleCtrlHandler(static_cast(CtrlHandler), TRUE)); - -#else - invariant( signal(SIGHUP , SIG_IGN ) != SIG_ERR ); - invariant( signal(SIGUSR2, SIG_IGN ) != SIG_ERR ); - invariant( signal(SIGPIPE, SIG_IGN) != SIG_ERR ); - - struct sigaction addrSignals; - memset( &addrSignals, 0, sizeof( struct sigaction ) ); - addrSignals.sa_sigaction = abruptQuitWithAddrSignal; - sigemptyset( &addrSignals.sa_mask ); - addrSignals.sa_flags = SA_SIGINFO; - - invariant( sigaction(SIGSEGV, &addrSignals, 0) == 0 ); - invariant( sigaction(SIGBUS, &addrSignals, 0) == 0 ); - invariant( sigaction(SIGILL, &addrSignals, 0) == 0 ); - invariant( sigaction(SIGFPE, &addrSignals, 0) == 0 ); - - - setupSIGTRAPforGDB(); - - // asyncSignals is a global variable listing the signals that should be handled by the - // interrupt thread, once it is started via startSignalProcessingThread(). - sigemptyset( &asyncSignals ); - sigaddset( &asyncSignals, SIGHUP ); - sigaddset( &asyncSignals, SIGINT ); - sigaddset( &asyncSignals, SIGTERM ); - sigaddset( &asyncSignals, SIGQUIT ); - sigaddset( &asyncSignals, SIGUSR1 ); - sigaddset( &asyncSignals, SIGXCPU ); -#endif - } - - void startSignalProcessingThread() { -#ifdef _WIN32 - boost::thread(eventProcessingThread).detach(); -#else - // Mask signals in the current (only) thread. All new threads will inherit this mask. - invariant( pthread_sigmask( SIG_SETMASK, &asyncSignals, 0 ) == 0 ); - // Spawn a thread to capture the signals we just masked off. - boost::thread( signalProcessingThread ).detach(); -#endif - } - -} // namespace mongo diff --git a/src/mongo/util/signal_handlers.h b/src/mongo/util/signal_handlers.h deleted file mode 100644 index d2a83257b3..0000000000 --- a/src/mongo/util/signal_handlers.h +++ /dev/null @@ -1,37 +0,0 @@ -// signal_handlers.h - -/* Copyright 2014 MongoDB Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -namespace mongo { - - /** - * Sets up handlers for signals and other events like terminate and new_handler. - * - * This must be called very early in main, before runGlobalInitializers(). - */ - void setupSignalHandlers(); - - /** - * Starts the thread to handle asynchronous signals. - * - * This must be the first thread started from the main thread. Call this immediately after - * initializeServerGlobalState(). - */ - void startSignalProcessingThread(); - -} // namespace mongo