diff --git a/src/launcherlib/daemon.cpp b/src/launcherlib/daemon.cpp index b461b41..453ab5d 100644 --- a/src/launcherlib/daemon.cpp +++ b/src/launcherlib/daemon.cpp @@ -96,7 +96,6 @@ Daemon::Daemon(int & argc, char * argv[]) : m_boosterPid(0), m_socketManager(new SocketManager), m_singleInstance(new SingleInstance), - m_reExec(false), m_notifySystemd(false), m_booster(0) { @@ -125,21 +124,16 @@ Daemon::Daemon(int & argc, char * argv[]) : // Parse arguments parseArgs(ArgVect(argv, argv + argc)); - if (m_reExec) - { - restoreState(); - } - // Store arguments list m_initialArgv = argv; m_initialArgc = argc; - if (!m_reExec && socketpair(AF_UNIX, SOCK_DGRAM, 0, m_boosterLauncherSocket) == -1) + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, m_boosterLauncherSocket) == -1) { throw std::runtime_error("Daemon: Creating a socket pair for boosters failed!\n"); } - if (!m_reExec && pipe(m_sigPipeFd) == -1) + if (pipe(m_sigPipeFd) == -1) { throw std::runtime_error("Daemon: Creating a pipe for Unix signals failed!\n"); } @@ -167,22 +161,13 @@ void Daemon::run(Booster *booster) // dlopen single-instance loadSingleInstancePlugin(); - if (m_reExec) - { - // Reap dead booster processes and restart them - // Note: this cannot be done before booster plugins have been loaded - reapZombies(); - } - else - { - // Create socket for the booster - Logger::logDebug("Daemon: initing socket: %s", booster->boosterType().c_str()); - m_socketManager->initSocket(booster->boosterType()); + // Create socket for the booster + Logger::logDebug("Daemon: initing socket: %s", booster->boosterType().c_str()); + m_socketManager->initSocket(booster->boosterType()); - // Fork each booster for the first time - Logger::logDebug("Daemon: forking booster: %s", booster->boosterType().c_str()); - forkBooster(); - } + // Fork each booster for the first time + Logger::logDebug("Daemon: forking booster: %s", booster->boosterType().c_str()); + forkBooster(); // Notify systemd that init is done if (m_notifySystemd) { @@ -251,14 +236,6 @@ void Daemon::run(Booster *booster) Logger::logDebug("Daemon: SIGPIPE received."); break; - case SIGHUP: - Logger::logDebug("Daemon: SIGHUP received."); - reExec(); - - // not reached if re-exec successful - break; - - default: break; } @@ -600,10 +577,6 @@ void Daemon::parseArgs(const ArgVect & args) { usage(args[0].c_str(), EXIT_SUCCESS); } - else if ((*i) == "--re-exec") - { - m_reExec = true; - } else if ((*i) == "--systemd") { m_notifySystemd = true; @@ -727,257 +700,3 @@ Daemon::~Daemon() Logger::closeLog(); } -void Daemon::reExec() -{ - Logger::logInfo("Daemon: Re-exec requested."); - - struct stat st; - if (stat(m_stateDir.c_str(), &st) != 0) - { - Logger::logDebug("Daemon: State saving directory %s does not exist", m_stateDir.c_str()); - Logger::logDebug("Daemon: Attempting to create it"); - - if (mkdir(m_stateDir.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) - { - Logger::logDebug("Daemon: Failed to create directory, re-exec failed, exiting."); - _exit(1); - } - } - - if (stat(m_stateDir.c_str(), &st) != 0) - { - Logger::logDebug("Daemon: Directory vanished, re-exec failed, exiting."); - _exit(1); - } - if (!S_ISDIR(st.st_mode)) - { - Logger::logDebug("Daemon: %s exists but it is not a directory, re-exec failed, exiting.", m_stateDir.c_str()); - _exit(1); - } - - try { - std::ofstream ss(m_stateFile.c_str()); - ss.exceptions (std::ifstream::failbit | std::ifstream::badbit); - - // dump the pid to double check that the state file is from this process - ss << "my-pid " << getpid() << std::endl; - - // Save debug mode first, restoring it will enable debug logging. - // This way we get debug output from the re-execed daemon as early - // as possible. - ss << "debug-mode " << m_debugMode << std::endl; - - // The pids of the dead boosters are also passed as children, but - // this causes no harm. - for(PidVect::iterator it = m_children.begin(); it != m_children.end(); it++) - { - ss << "child " << *it << std::endl; - } - - for(PidMap::iterator it = m_boosterPidToInvokerPid.begin(); it != m_boosterPidToInvokerPid.end(); it++) - { - ss << "booster-invoker-pid " << it->first << " " << it->second << std::endl; - } - - for(FdMap::iterator it = m_boosterPidToInvokerFd.begin(); it != m_boosterPidToInvokerFd.end(); it++) - { - ss << "booster-invoker-fd " << it->first << " " << it->second << std::endl; - } - - ss << "booster-pid " << m_boosterPid << std::endl; - - ss << "launcher-socket " << m_boosterLauncherSocket[0] << " " << m_boosterLauncherSocket[1] << std::endl; - - ss << "sigpipe-fd " << m_sigPipeFd[0] << " " << m_sigPipeFd[1] << std::endl; - - ss << "boot-mode " << m_bootMode << std::endl; - - SocketManager::SocketHash s = m_socketManager->getState(); - for(SocketManager::SocketHash::iterator it = s.begin(); it != s.end(); it++) - { - ss << "socket-hash " << it->first << " " << it->second << std::endl; - } - - // when the new applauncherd reads this, - // it knows state saving was successful. - ss << "end" << std::endl; - ss.close(); - } - catch (std::ofstream::failure e) - { - Logger::logError("Daemon: Failed to save state, re-exec failed, exiting."); - _exit(1); - } - - char* argv[] = { const_cast("/usr/bin/applauncherd.bin"), - const_cast("--re-exec"), - const_cast(" "), - NULL}; - - // The boosters have state which will become stale, so kill them. - // The dead boosters will be reaped when the re-execed applauncherd - // calls reapZombies after it has initialized. - killBoosters(); - - // Signal handlers are reset at exec(), so we will lose - // the SIGHUP handling. However, ignoring a signal is preserved - // over exec(), so start ignoring SIGHUP to prevent applauncherd - // dying if we receive multiple SIGHUPs. - signal(SIGHUP, SIG_IGN); - - Logger::logDebug("Daemon: configuration saved succesfully, call execve() "); - execve(argv[0], argv, environ); - - // Not reached. - Logger::logDebug("Daemon: Failed to execute execve(), re-exec failed, exiting."); - _exit(1); -} - -void Daemon::restoreState() -{ - try - { - // We have saved state, try to restore it. - std::ifstream ss(m_stateFile.c_str()); - ss.exceptions (std::ifstream::failbit | std::ifstream::badbit); - - std::string token; - - ss >> token; - - // Bit of defensive programming. Read the pid of the process - // that left the state file. If it is different from my pid, - // then something is wrong, and we better exit. - if (token != "my-pid") - { - throw "Daemon: malformed state file, exiting."; - } - else - { - int pid; - ss >> pid; - if (pid != getpid()) - { - throw "Daemon: stale state file, exiting."; - } - } - - // Do not check for eof, instead trigger an exception - // if reading past end of file. When state restore is - // successful we read the "end" token and return from - // this method. - while (true) - { - ss >> token; - - if (token == "end") - { - // successfully restored state - ss.close(); - - // In debug mode it is better to leave the file there - // so it can be examined. - if (!m_debugMode && remove(m_stateFile.c_str()) == -1) - { - Logger::logError("Daemon: could not remove state file %s", m_stateFile.c_str()); - } - Logger::logDebug("Daemon: state restore completed"); - return; - } - else if (token == "child") - { - int arg1; - ss >> arg1; - Logger::logDebug("Daemon: restored child %d", arg1); - m_children.push_back(arg1); - } - else if (token == "booster-invoker-pid") - { - int arg1, arg2; - ss >> arg1; - ss >> arg2; - Logger::logDebug("Daemon: restored m_boosterPidToInvokerPid[%d] = %d", arg1, arg2); - m_boosterPidToInvokerPid[arg1] = arg2; - } - else if (token == "booster-invoker-fd") - { - int arg1, arg2; - ss >> arg1; - ss >> arg2; - Logger::logDebug("Daemon: restored m_boosterPidToInvokerFd[%d] = %d", arg1, arg2); - m_boosterPidToInvokerFd[arg1] = arg2; - } - else if (token == "booster-pid") - { - int arg1; - ss >> arg1; - Logger::logDebug("Daemon: restored m_boosterPid = %d", arg1); - - m_boosterPid = arg1; - } - else if (token == "launcher-socket") - { - int arg1, arg2; - ss >> arg1; - ss >> arg2; - Logger::logDebug("Daemon: restored m_boosterLauncherSocket[] = {%d, %d}", arg1, arg2); - m_boosterLauncherSocket[0] = arg1; - m_boosterLauncherSocket[1] = arg2; - } - else if (token == "sigpipe-fd") - { - int arg1, arg2; - ss >> arg1; - ss >> arg2; - Logger::logDebug("Daemon: restored m_sigPipeFd[] = {%d, %d}", arg1, arg2); - m_sigPipeFd[0] = arg1; - m_sigPipeFd[1] = arg2; - } - else if (token == "socket-hash") - { - std::string arg1; - int arg2; - ss >> arg1; - ss >> arg2; - m_socketManager->addMapping(arg1, arg2); - Logger::logDebug("Daemon: restored socketHash[%s] = %d", arg1.c_str(), arg2); - } - else if (token == "debug-mode") - { - bool arg1; - ss >> arg1; - m_debugMode = arg1; - Logger::setDebugMode(m_debugMode); - Logger::logDebug("Daemon: restored m_debugMode = %d", arg1); - } - else if (token == "boot-mode") - { - bool arg1; - ss >> arg1; - m_bootMode = arg1; - Logger::logDebug("Daemon: restored m_bootMode = %d", arg1); - } - } - } - catch (std::ifstream::failure e) - { - // Ran out of saved state before "end" token - // or there was some other error in restoring the sate. - Logger::logError("Daemon: Failed to restore saved state, exiting."); - } - catch (char *err) - { - // Some other error, e.g. stale state file - Logger::logError(err); - } - - // In debug mode it is better to leave the file there - // so it can be examined. - if (!m_debugMode && remove(m_stateFile.c_str()) == -1) - { - Logger::logError("Daemon: could not remove state file %s", m_stateFile.c_str()); - } - - // This is only reached if state restore was unsuccessful. - _exit(1); -} diff --git a/src/launcherlib/daemon.h b/src/launcherlib/daemon.h index 502a14e..2c969ee 100644 --- a/src/launcherlib/daemon.h +++ b/src/launcherlib/daemon.h @@ -144,12 +144,6 @@ private: //! Prints the usage and exits with given status void usage(const char *name, int status); - //! Re-exec applauncherd.bin - void reExec(); - - //! Restore state. - void restoreState(); - //! Daemonize flag (--fork). Daemon forks if true. bool m_daemon; @@ -208,9 +202,6 @@ private: typedef map SigHandlerMap; SigHandlerMap m_originalSigHandlers; - //! True if re-execing - bool m_reExec; - //! True if systemd needs to be notified bool m_notifySystemd;