int ServerApplication::init(int argc, char *argv[]) { // Hide child's output if (hasFeature(FEATURE_SERVER) && options["child"].toBoolean()) options["log-to-screen"].setDefault(false); int ret = Application::init(argc, argv); if (ret == -1) return -1; if (!hasFeature(FEATURE_SERVER)) return ret; if (!options["child"].toBoolean()) { #ifndef _WIN32 if (options["fork"].toBoolean()) { // Note, all threads must be stopped before daemonize() forks and // SignalManager runs in a thread. SignalManager::instance().setEnabled(false); SystemUtilities::daemonize(); SignalManager::instance().setEnabled(true); } #endif if (options["pid"].toBoolean()) { // Try to acquire an exclusive lock new ProcessLock(options["pid-file"], 10); // OK to leak LOG_INFO(1, "Acquired exclusive lock on " << options["pid-file"]); } } #ifndef _WIN32 try { if (options["run-as"].hasValue()) { LOG_INFO(1, "Switching to user " << options["run-as"]); SystemUtilities::setUser(options["run-as"]); } } CBANG_CATCH_ERROR; #endif if (!options["child"].toBoolean() && options["respawn"].toBoolean()) { #ifndef _WIN32 // Child restart handler SignalManager::instance().addHandler(SIGUSR1, this); #endif // Setup child arguments vector<string> args; args.push_back(argv[0]); args.push_back((char *)"--child"); args.push_back((char *)"--lifeline"); args.push_back(String(SystemUtilities::getPID())); args.insert(args.end(), argv + 1, argv + argc); unsigned lastRespawn = 0; unsigned respawnCount = 0; while (!shouldQuit()) { // Check respawn rate unsigned now = Time::now(); if (now - lastRespawn < 60) { if (++respawnCount == 5) { LOG_ERROR("Respawning too fast. Exiting."); break; } } else respawnCount = 0; lastRespawn = now; // Spawn child Subprocess child; child.exec(args, Subprocess::NULL_STDOUT | Subprocess::NULL_STDERR); uint64_t killTime = 0; while (child.isRunning()) { if (!killTime && (restartChild || shouldQuit())) { LOG_INFO(1, "Shutting down child at PID=" << child.getPID()); child.interrupt(); restartChild = false; killTime = Time::now() + 300; // Give it 5 mins to shutdown } if (killTime && killTime < Time::now()) { LOG_INFO(1, "Child failed to shutdown cleanly, killing"); killTime = 0; child.kill(); } Timer::sleep(0.1); } LOG_INFO(1, "Child exited with return code " << child.getReturnCode()); } exit(0); } return ret; }