void CheckVersionFeature::validateOptions( std::shared_ptr<ProgramOptions> options) { if (!_checkVersion) { return; } ApplicationServer::forceDisableFeatures(_nonServerFeatures); LoggerFeature* logger = ApplicationServer::getFeature<LoggerFeature>("Logger"); logger->disableThreaded(); DatabaseFeature* databaseFeature = ApplicationServer::getFeature<DatabaseFeature>("Database"); databaseFeature->disableReplicationApplier(); databaseFeature->enableCheckVersion(); V8DealerFeature* v8dealer = ApplicationServer::getFeature<V8DealerFeature>("V8Dealer"); v8dealer->setNumberContexts(1); }
void SupervisorFeature::daemonize() { static time_t const MIN_TIME_ALIVE_IN_SEC = 30; if (!_supervisor) { return; } time_t startTime = time(0); time_t t; bool done = false; int result = EXIT_SUCCESS; std::vector<ApplicationFeature*> supervisorFeatures(_supervisorStart.size()); std::transform(_supervisorStart.begin(), _supervisorStart.end(), supervisorFeatures.begin(), [](std::string const& name) { try { return ApplicationServer::getFeature<ApplicationFeature>(name); } catch (...) { LOG_TOPIC(FATAL, Logger::STARTUP) << "unknown feature '" << name << "', giving up"; FATAL_ERROR_EXIT(); } }); while (!done) { // fork of the server _clientPid = fork(); if (_clientPid < 0) { LOG_TOPIC(FATAL, Logger::STARTUP) << "fork failed, giving up"; FATAL_ERROR_EXIT(); } // parent (supervisor) if (0 < _clientPid) { TRI_SetProcessTitle("arangodb [supervisor]"); std::for_each(supervisorFeatures.begin(), supervisorFeatures.end(), [](ApplicationFeature* feature) { LoggerFeature* logger = dynamic_cast<LoggerFeature*>(feature); if (logger != nullptr) { logger->setSupervisor(true); logger->disableThreaded(); } }); std::for_each(supervisorFeatures.begin(), supervisorFeatures.end(), [](ApplicationFeature* feature) { feature->prepare(); }); std::for_each(supervisorFeatures.begin(), supervisorFeatures.end(), [](ApplicationFeature* feature) { feature->start(); }); LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor mode: within parent"; ArangoGlobalContext::CONTEXT->unmaskStandardSignals(); signal(SIGINT, StopHandler); signal(SIGTERM, StopHandler); CLIENT_PID = _clientPid; DONE = false; int status; int res = waitpid(_clientPid, &status, 0); bool horrible = true; if (!DONE) { done = true; horrible = false; } else { LOG_TOPIC(DEBUG, Logger::STARTUP) << "waitpid woke up with return value " << res << " and status " << status; if (WIFEXITED(status)) { // give information about cause of death if (WEXITSTATUS(status) == 0) { LOG_TOPIC(INFO, Logger::STARTUP) << "child " << _clientPid << " died of natural causes"; done = true; horrible = false; } else { t = time(0) - startTime; LOG_TOPIC(ERR, Logger::STARTUP) << "child " << _clientPid << " died a horrible death, exit status " << WEXITSTATUS(status); if (t < MIN_TIME_ALIVE_IN_SEC) { LOG_TOPIC(ERR, Logger::STARTUP) << "child only survived for " << t << " seconds, this will not work - please fix the error " "first"; done = true; } else { done = false; } } } else if (WIFSIGNALED(status)) { switch (WTERMSIG(status)) { case 2: case 9: case 15: LOG_TOPIC(INFO, Logger::STARTUP) << "child " << _clientPid << " died of natural causes, exit status " << WTERMSIG(status); done = true; horrible = false; break; default: t = time(0) - startTime; LOG_TOPIC(ERR, Logger::STARTUP) << "child " << _clientPid << " died a horrible death, signal " << WTERMSIG(status); if (t < MIN_TIME_ALIVE_IN_SEC) { LOG_TOPIC(ERR, Logger::STARTUP) << "child only survived for " << t << " seconds, this will not work - please fix the " "error first"; done = true; #ifdef WCOREDUMP if (WCOREDUMP(status)) { LOG_TOPIC(WARN, Logger::STARTUP) << "child process " << _clientPid << " produced a core dump"; } #endif } else { done = false; } break; } } else { LOG_TOPIC(ERR, Logger::STARTUP) << "child " << _clientPid << " died a horrible death, unknown cause"; done = false; } } if (horrible) { result = EXIT_FAILURE; } } // child - run the normal boot sequence else { LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor mode: within child"; TRI_SetProcessTitle("arangodb [server]"); #ifdef TRI_HAVE_PRCTL // force child to stop if supervisor dies prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); #endif try { DaemonFeature* daemon = ApplicationServer::getFeature<DaemonFeature>("Daemon"); // disable daemon mode daemon->setDaemon(false); } catch (...) { } return; } } std::for_each(supervisorFeatures.rbegin(), supervisorFeatures.rend(), [](ApplicationFeature* feature) { feature->stop(); }); std::for_each(supervisorFeatures.rbegin(), supervisorFeatures.rend(), [](ApplicationFeature* feature) { feature->unprepare(); }); exit(result); }