void setupSignalHandlers() { setupSIGTRAPforGDB(); setupCoreSignals(); signal(SIGTERM, sighandler); signal(SIGINT, sighandler); #if defined(SIGQUIT) signal( SIGQUIT , printStackAndExit ); #endif signal( SIGSEGV , printStackAndExit ); signal( SIGABRT , printStackAndExit ); signal( SIGFPE , printStackAndExit ); #if defined(SIGBUS) signal( SIGBUS , printStackAndExit ); #endif #if defined(SIGPIPE) signal( SIGPIPE , SIG_IGN ); #endif #ifndef _WIN32 sigemptyset( &asyncSignals ); sigaddset( &asyncSignals, SIGUSR1 ); startSignalProcessingThread(); #endif setWindowsUnhandledExceptionFilter(); set_new_handler( my_new_handler ); }
void init() { serverID.init(); setupSIGTRAPforGDB(); setupCoreSignals(); setupSignals( false ); Logstream::get().addGlobalTee( new RamLog("global") ); }
bool CmdLine::store( int argc , char ** argv , boost::program_options::options_description& visible, boost::program_options::options_description& hidden, boost::program_options::positional_options_description& positional, boost::program_options::variables_map ¶ms ){ { // setup binary name cmdLine.binaryName = argv[0]; size_t i = cmdLine.binaryName.rfind( '/' ); if ( i != string::npos ) cmdLine.binaryName = cmdLine.binaryName.substr( i + 1 ); } /* don't allow guessing - creates ambiguities when some options are * prefixes of others. allow long disguises and don't allow guessing * to get away with our vvvvvvv trick. */ int style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::options_description all; all.add( visible ); all.add( hidden ); po::store( po::command_line_parser(argc, argv) .options( all ) .positional( positional ) .style( style ) .run(), params ); if ( params.count("config") ){ ifstream f( params["config"].as<string>().c_str() ); if ( ! f.is_open() ){ cout << "ERROR: could not read from config file" << endl << endl; cout << visible << endl; return false; } po::store( po::parse_config_file( f , all ) , params ); f.close(); } po::notify(params); } catch (po::error &e) { cout << "error command line: " << e.what() << endl; cout << "use --help for help" << endl; //cout << visible << endl; return false; } if (params.count("verbose")) { logLevel = 1; } for (string s = "vv"; s.length() <= 12; s.append("v")) { if (params.count(s)) { logLevel = s.length(); } } if (params.count("quiet")) { cmdLine.quiet = true; } string logpath; #ifndef _WIN32 if (params.count("fork")) { if ( ! params.count( "logpath" ) ){ cout << "--fork has to be used with --logpath" << endl; ::exit(-1); } { // test logpath logpath = params["logpath"].as<string>(); assert( logpath.size() ); if ( logpath[0] != '/' ){ char temp[256]; assert( getcwd( temp , 256 ) ); logpath = (string)temp + "/" + logpath; } FILE * test = fopen( logpath.c_str() , "a" ); if ( ! test ){ cout << "can't open [" << logpath << "] for log file: " << errnoWithDescription() << endl; ::exit(-1); } fclose( test ); } cout.flush(); cerr.flush(); pid_t c = fork(); if ( c ){ _exit(0); } if ( chdir("/") < 0 ){ cout << "Cant chdir() while forking server process: " << strerror(errno) << endl; ::exit(-1); } setsid(); pid_t c2 = fork(); if ( c2 ){ cout << "forked process: " << c2 << endl; _exit(0); } // stdout handled in initLogging //fclose(stdout); //freopen("/dev/null", "w", stdout); fclose(stderr); fclose(stdin); FILE* f = freopen("/dev/null", "w", stderr); if ( f == NULL ){ cout << "Cant reassign stderr while forking server process: " << strerror(errno) << endl; ::exit(-1); } f = freopen("/dev/null", "r", stdin); if ( f == NULL ){ cout << "Cant reassign stdin while forking server process: " << strerror(errno) << endl; ::exit(-1); } setupCoreSignals(); setupSignals( true ); } #endif if (params.count("logpath")) { if ( logpath.size() == 0 ) logpath = params["logpath"].as<string>(); uassert( 10033 , "logpath has to be non-zero" , logpath.size() ); initLogging( logpath , params.count( "logappend" ) ); } if ( params.count("pidfilepath")) { writePidFile( params["pidfilepath"].as<string>() ); } if (params.count("keyFile")){ const string f = params["keyFile"].as<string>(); if (!setUpSecurityKey(f)) { // error message printed in setUpPrivateKey dbexit(EXIT_BADOPTIONS); } noauth = false; } { BSONArrayBuilder b; for (int i=0; i < argc; i++) b << argv[i]; argvArray = b.arr(); } return true; }
void init(){ serverID.init(); setupSIGTRAPforGDB(); setupCoreSignals(); setupSignals( false ); }
bool CmdLine::store( int argc , char ** argv , boost::program_options::options_description& visible, boost::program_options::options_description& hidden, boost::program_options::positional_options_description& positional, boost::program_options::variables_map ¶ms ) { { // setup binary name cmdLine.binaryName = argv[0]; size_t i = cmdLine.binaryName.rfind( '/' ); if ( i != string::npos ) cmdLine.binaryName = cmdLine.binaryName.substr( i + 1 ); // setup cwd char buffer[1024]; #ifdef _WIN32 verify( _getcwd( buffer , 1000 ) ); #else verify( getcwd( buffer , 1000 ) ); #endif cmdLine.cwd = buffer; } /* don't allow guessing - creates ambiguities when some options are * prefixes of others. allow long disguises and don't allow guessing * to get away with our vvvvvvv trick. */ int style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::options_description all; all.add( visible ); all.add( hidden ); po::store( po::command_line_parser(argc, argv) .options( all ) .positional( positional ) .style( style ) .run(), params ); if ( params.count("config") ) { ifstream f( params["config"].as<string>().c_str() ); if ( ! f.is_open() ) { cout << "ERROR: could not read from config file" << endl << endl; cout << visible << endl; return false; } stringstream ss; CmdLine::parseConfigFile( f, ss ); po::store( po::parse_config_file( ss , all ) , params ); f.close(); } po::notify(params); } catch (po::error &e) { cout << "error command line: " << e.what() << endl; cout << "use --help for help" << endl; //cout << visible << endl; return false; } if (params.count("verbose")) { logLevel = 1; } for (string s = "vv"; s.length() <= 12; s.append("v")) { if (params.count(s)) { logLevel = s.length(); } } if (params.count("quiet")) { cmdLine.quiet = true; } if ( params.count( "maxConns" ) ) { int newSize = params["maxConns"].as<int>(); if ( newSize < 5 ) { out() << "maxConns has to be at least 5" << endl; ::_exit( EXIT_BADOPTIONS ); } else if ( newSize >= 10000000 ) { out() << "maxConns can't be greater than 10000000" << endl; ::_exit( EXIT_BADOPTIONS ); } connTicketHolder.resize( newSize ); } if (params.count("objcheck")) { cmdLine.objcheck = true; } if (params.count("bind_ip")) { // passing in wildcard is the same as default behavior; remove and warn if ( cmdLine.bind_ip == "0.0.0.0" ) { cout << "warning: bind_ip of 0.0.0.0 is unnecessary; listens on all ips by default" << endl; cmdLine.bind_ip = ""; } } string logpath; #ifndef _WIN32 if (params.count("unixSocketPrefix")) { cmdLine.socket = params["unixSocketPrefix"].as<string>(); if (!fs::is_directory(cmdLine.socket)) { cout << cmdLine.socket << " must be a directory" << endl; ::_exit(-1); } } if (params.count("nounixsocket")) { cmdLine.noUnixSocket = true; } if (params.count("fork") && !params.count("shutdown")) { cmdLine.doFork = true; if ( ! params.count( "logpath" ) && ! params.count( "syslog" ) ) { cout << "--fork has to be used with --logpath or --syslog" << endl; ::_exit(EXIT_BADOPTIONS); } if ( params.count( "logpath" ) ) { // test logpath logpath = params["logpath"].as<string>(); verify( logpath.size() ); if ( logpath[0] != '/' ) { logpath = cmdLine.cwd + "/" + logpath; } bool exists = boost::filesystem::exists( logpath ); FILE * test = fopen( logpath.c_str() , "a" ); if ( ! test ) { cout << "can't open [" << logpath << "] for log file: " << errnoWithDescription() << endl; ::_exit(-1); } fclose( test ); // if we created a file, unlink it (to avoid confusing log rotation code) if ( ! exists ) { unlink( logpath.c_str() ); } } cout.flush(); cerr.flush(); cmdLine.parentProc = getpid(); // facilitate clean exit when child starts successfully setupLaunchSignals(); pid_t c = fork(); if ( c ) { int pstat; waitpid(c, &pstat, 0); if ( WIFEXITED(pstat) ) { if ( ! WEXITSTATUS(pstat) ) { cout << "child process started successfully, parent exiting" << endl; } _exit( WEXITSTATUS(pstat) ); } _exit(50); } if ( chdir("/") < 0 ) { cout << "Cant chdir() while forking server process: " << strerror(errno) << endl; ::_exit(-1); } setsid(); cmdLine.leaderProc = getpid(); pid_t c2 = fork(); if ( c2 ) { int pstat; cout << "forked process: " << c2 << endl; waitpid(c2, &pstat, 0); if ( WIFEXITED(pstat) ) { _exit( WEXITSTATUS(pstat) ); } _exit(51); } // stdout handled in initLogging //fclose(stdout); //freopen("/dev/null", "w", stdout); fclose(stderr); fclose(stdin); FILE* f = freopen("/dev/null", "w", stderr); if ( f == NULL ) { cout << "Cant reassign stderr while forking server process: " << strerror(errno) << endl; ::_exit(-1); } f = freopen("/dev/null", "r", stdin); if ( f == NULL ) { cout << "Cant reassign stdin while forking server process: " << strerror(errno) << endl; ::_exit(-1); } setupCoreSignals(); setupSignals( true ); } if (params.count("syslog")) { StringBuilder sb; sb << cmdLine.binaryName << "." << cmdLine.port; Logstream::useSyslog( sb.str().c_str() ); } #endif if (params.count("logpath") && !params.count("shutdown")) { if ( params.count("syslog") ) { cout << "Cant use both a logpath and syslog " << endl; ::_exit(EXIT_BADOPTIONS); } if ( logpath.size() == 0 ) logpath = params["logpath"].as<string>(); uassert( 10033 , "logpath has to be non-zero" , logpath.size() ); initLogging( logpath , params.count( "logappend" ) ); } if ( params.count("pidfilepath")) { writePidFile( params["pidfilepath"].as<string>() ); } if (params.count("keyFile")) { const string f = params["keyFile"].as<string>(); if (!setUpSecurityKey(f)) { // error message printed in setUpPrivateKey ::_exit(EXIT_BADOPTIONS); } cmdLine.keyFile = true; noauth = false; } else { cmdLine.keyFile = false; } #ifdef MONGO_SSL if (params.count("sslOnNormalPorts") ) { cmdLine.sslOnNormalPorts = true; if ( cmdLine.sslPEMKeyPassword.size() == 0 ) { log() << "need sslPEMKeyPassword" << endl; ::_exit(EXIT_BADOPTIONS); } if ( cmdLine.sslPEMKeyFile.size() == 0 ) { log() << "need sslPEMKeyFile" << endl; ::_exit(EXIT_BADOPTIONS); } cmdLine.sslServerManager = new SSLManager( false ); cmdLine.sslServerManager->setupPEM( cmdLine.sslPEMKeyFile , cmdLine.sslPEMKeyPassword ); } else if ( cmdLine.sslPEMKeyFile.size() || cmdLine.sslPEMKeyPassword.size() ) { log() << "need to enable sslOnNormalPorts" << endl; ::_exit(EXIT_BADOPTIONS); } #endif { BSONObjBuilder b; for (po::variables_map::const_iterator it(params.begin()), end(params.end()); it != end; it++){ if (!it->second.defaulted()){ const string& key = it->first; const po::variable_value& value = it->second; const type_info& type = value.value().type(); if (type == typeid(string)){ if (value.as<string>().empty()) b.appendBool(key, true); // boost po uses empty string for flags like --quiet else { if ( key == "servicePassword" ) { b.append( key, "<password>" ); } else { b.append( key, value.as<string>() ); } } } else if (type == typeid(int)) b.append(key, value.as<int>()); else if (type == typeid(double)) b.append(key, value.as<double>()); else if (type == typeid(bool)) b.appendBool(key, value.as<bool>()); else if (type == typeid(long)) b.appendNumber(key, (long long)value.as<long>()); else if (type == typeid(unsigned)) b.appendNumber(key, (long long)value.as<unsigned>()); else if (type == typeid(unsigned long long)) b.appendNumber(key, (long long)value.as<unsigned long long>()); else if (type == typeid(vector<string>)) b.append(key, value.as<vector<string> >()); else b.append(key, "UNKNOWN TYPE: " + demangleName(type)); } } parsedOpts = b.obj(); } { BSONArrayBuilder b; for (int i=0; i < argc; i++) b << argv[i]; argvArray = b.arr(); } return true; }
bool initializeServerGlobalState(bool isMongodShutdownSpecialCase) { Listener::globalTicketHolder.resize( cmdLine.maxConns ); #ifndef _WIN32 if (!fs::is_directory(cmdLine.socket)) { cout << cmdLine.socket << " must be a directory" << endl; return false; } if (cmdLine.doFork) { fassert(16447, !cmdLine.logpath.empty() || cmdLine.logWithSyslog); cout.flush(); cerr.flush(); cmdLine.parentProc = getpid(); // facilitate clean exit when child starts successfully setupLaunchSignals(); pid_t c = fork(); if ( c ) { int pstat; waitpid(c, &pstat, 0); if ( WIFEXITED(pstat) ) { if ( ! WEXITSTATUS(pstat) ) { cout << "child process started successfully, parent exiting" << endl; } _exit( WEXITSTATUS(pstat) ); } _exit(50); } if ( chdir("/") < 0 ) { cout << "Cant chdir() while forking server process: " << strerror(errno) << endl; ::_exit(-1); } setsid(); cmdLine.leaderProc = getpid(); pid_t c2 = fork(); if ( c2 ) { int pstat; cout << "forked process: " << c2 << endl; waitpid(c2, &pstat, 0); if ( WIFEXITED(pstat) ) { _exit( WEXITSTATUS(pstat) ); } _exit(51); } // stdout handled in initLogging //fclose(stdout); //freopen("/dev/null", "w", stdout); fclose(stderr); fclose(stdin); FILE* f = freopen("/dev/null", "w", stderr); if ( f == NULL ) { cout << "Cant reassign stderr while forking server process: " << strerror(errno) << endl; return false; } f = freopen("/dev/null", "r", stdin); if ( f == NULL ) { cout << "Cant reassign stdin while forking server process: " << strerror(errno) << endl; return false; } setupCoreSignals(); setupSignals( true ); } if (cmdLine.logWithSyslog) { StringBuilder sb; sb << cmdLine.binaryName << "." << cmdLine.port; Logstream::useSyslog( sb.str().c_str() ); } #endif if (!cmdLine.logpath.empty() && !isMongodShutdownSpecialCase) { fassert(16448, !cmdLine.logWithSyslog); string absoluteLogpath = boost::filesystem::absolute( cmdLine.logpath, cmdLine.cwd).string(); if (!initLogging(absoluteLogpath, cmdLine.logAppend)) { cout << "Bad logpath value: \"" << absoluteLogpath << "\"; terminating." << endl; return false; } } if (!cmdLine.pidFile.empty()) { writePidFile(cmdLine.pidFile); } if (!cmdLine.keyFile.empty()) { if (!setUpSecurityKey(cmdLine.keyFile)) { // error message printed in setUpPrivateKey return false; } noauth = false; } #ifdef MONGO_SSL if (cmdLine.sslOnNormalPorts) { if ( cmdLine.sslPEMKeyPassword.size() == 0 ) { log() << "need sslPEMKeyPassword" << endl; return false; } if ( cmdLine.sslPEMKeyFile.size() == 0 ) { log() << "need sslPEMKeyFile" << endl; return false; } cmdLine.sslServerManager = new SSLManager( false ); if ( ! cmdLine.sslServerManager->setupPEM( cmdLine.sslPEMKeyFile , cmdLine.sslPEMKeyPassword ) ) { return false; } } else if ( cmdLine.sslPEMKeyFile.size() || cmdLine.sslPEMKeyPassword.size() ) { log() << "need to enable sslOnNormalPorts" << endl; return false; } #endif return true; }
bool CmdLine::store( int argc , char ** argv , boost::program_options::options_description& visible, boost::program_options::options_description& hidden, boost::program_options::positional_options_description& positional, boost::program_options::variables_map ¶ms ){ /* don't allow guessing - creates ambiguities when some options are * prefixes of others. allow long disguises and don't allow guessing * to get away with our vvvvvvv trick. */ int style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::options_description all; all.add( visible ); all.add( hidden ); po::store( po::command_line_parser(argc, argv) .options( all ) .positional( positional ) .style( style ) .run(), params ); if ( params.count("config") ){ ifstream f( params["config"].as<string>().c_str() ); if ( ! f.is_open() ){ cout << "ERROR: could not read from config file" << endl << endl; cout << visible << endl; return false; } po::store( po::parse_config_file( f , all ) , params ); f.close(); } po::notify(params); } catch (po::error &e) { cout << "ERROR: " << e.what() << endl << endl; cout << visible << endl; return false; } if (params.count("verbose")) { logLevel = 1; } for (string s = "vv"; s.length() <= 12; s.append("v")) { if (params.count(s)) { logLevel = s.length(); } } if (params.count("quiet")) { cmdLine.quiet = true; } #ifndef _WIN32 if (params.count("fork")) { if ( ! params.count( "logpath" ) ){ cout << "--fork has to be used with --logpath" << endl; ::exit(-1); } cout.flush(); cerr.flush(); pid_t c = fork(); if ( c ){ _exit(0); } chdir("/"); setsid(); pid_t c2 = fork(); if ( c2 ){ cout << "forked process: " << c2 << endl; _exit(0); } // stdout handled in initLogging //fclose(stdout); //freopen("/dev/null", "w", stdout); fclose(stderr); freopen("/dev/null", "w", stderr); fclose(stdin); freopen("/dev/null", "r", stdin); setupCoreSignals(); setupSignals(); } #endif if (params.count("logpath")) { string lp = params["logpath"].as<string>(); uassert( 10033 , "logpath has to be non-zero" , lp.size() ); initLogging( lp , params.count( "logappend" ) ); } { BSONArrayBuilder b; for (int i=0; i < argc; i++) b << argv[i]; argvArray = b.arr(); } return true; }
bool initializeServerGlobalState(bool isMongodShutdownSpecialCase) { Listener::globalTicketHolder.resize( cmdLine.maxConns ); #ifndef _WIN32 if (!fs::is_directory(cmdLine.socket)) { cout << cmdLine.socket << " must be a directory" << endl; return false; } if (cmdLine.doFork) { fassert(16447, !cmdLine.logpath.empty() || cmdLine.logWithSyslog); cout.flush(); cerr.flush(); cmdLine.parentProc = getpid(); // facilitate clean exit when child starts successfully setupLaunchSignals(); cout << "about to fork child process, waiting until server is ready for connections." << endl; pid_t child1 = fork(); if (child1 == -1) { cout << "ERROR: stage 1 fork() failed: " << errnoWithDescription(); _exit(EXIT_ABRUPT); } else if (child1) { // this is run in the original parent process int pstat; waitpid(child1, &pstat, 0); if (WIFEXITED(pstat)) { if (WEXITSTATUS(pstat)) { cout << "ERROR: child process failed, exited with error number " << WEXITSTATUS(pstat) << endl; } else { cout << "child process started successfully, parent exiting" << endl; } _exit(WEXITSTATUS(pstat)); } _exit(50); } if ( chdir("/") < 0 ) { cout << "Cant chdir() while forking server process: " << strerror(errno) << endl; ::_exit(-1); } setsid(); cmdLine.leaderProc = getpid(); pid_t child2 = fork(); if (child2 == -1) { cout << "ERROR: stage 2 fork() failed: " << errnoWithDescription(); _exit(EXIT_ABRUPT); } else if (child2) { // this is run in the middle process int pstat; cout << "forked process: " << child2 << endl; waitpid(child2, &pstat, 0); if ( WIFEXITED(pstat) ) { _exit( WEXITSTATUS(pstat) ); } _exit(51); } // this is run in the final child process (the server) // stdout handled in initLogging //fclose(stdout); //freopen("/dev/null", "w", stdout); fclose(stderr); fclose(stdin); FILE* f = freopen("/dev/null", "w", stderr); if ( f == NULL ) { cout << "Cant reassign stderr while forking server process: " << strerror(errno) << endl; return false; } f = freopen("/dev/null", "r", stdin); if ( f == NULL ) { cout << "Cant reassign stdin while forking server process: " << strerror(errno) << endl; return false; } setupCoreSignals(); setupSignals( true ); } if (cmdLine.logWithSyslog) { StringBuilder sb; sb << cmdLine.binaryName << "." << cmdLine.port; Logstream::useSyslog( sb.str().c_str() ); } #endif if (!cmdLine.logpath.empty() && !isMongodShutdownSpecialCase) { fassert(16448, !cmdLine.logWithSyslog); string absoluteLogpath = boost::filesystem::absolute( cmdLine.logpath, cmdLine.cwd).string(); if (!initLogging(absoluteLogpath, cmdLine.logAppend)) { cout << "Bad logpath value: \"" << absoluteLogpath << "\"; terminating." << endl; return false; } } if (!cmdLine.pidFile.empty()) { writePidFile(cmdLine.pidFile); } if (!cmdLine.keyFile.empty()) { if (!setUpSecurityKey(cmdLine.keyFile)) { // error message printed in setUpPrivateKey return false; } noauth = false; } return true; }