diff --git a/CMakeLists.txt b/CMakeLists.txt index 66b90b1..270d5fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,9 @@ project(Applauncherd) cmake_minimum_required(VERSION 2.6) cmake_policy(VERSION 2.6) -set(CMAKE_VERBOSE_MAKEFILE ON) +# +# NOTE: For verbose build use VERBOSE=1 +# # Default C++-flags. Sub-builds might alter these. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -Wextra -g -O3 -Wl,--as-needed") @@ -78,6 +80,8 @@ add_definitions(-DBOOSTER_PLUGIN_DIR="/usr/lib/applauncherd") add_definitions(-DSINGLE_INSTANCE_PATH="/usr/bin/single-instance") # Disable debug logging, only error and warning messages get logged +# Currently effective only for invoker. Launcher part recognizes --debug +# which enables console echoing and debug messages. add_definitions(-DDEBUG_LOGGING_DISABLED) # Build with test coverage switch if BUILD_COVERAGE environment variable is set diff --git a/src/invoker/invoker.c b/src/invoker/invoker.c index fb5eb2e..db15d67 100644 --- a/src/invoker/invoker.c +++ b/src/invoker/invoker.c @@ -49,7 +49,7 @@ // Delay before exit static const unsigned int DEFAULT_DELAY = 0; -static const unsigned int RESPAWN_DELAY = 2; +static const unsigned int RESPAWN_DELAY = 3; static const unsigned int MAX_RESPAWN_DELAY = 10; static const unsigned char EXIT_STATUS_APPLICATION_CONNECTION_LOST = 0xfa; diff --git a/src/launcherlib/booster.cpp b/src/launcherlib/booster.cpp index b44dbd9..95d9b79 100644 --- a/src/launcherlib/booster.cpp +++ b/src/launcherlib/booster.cpp @@ -52,7 +52,8 @@ Booster::Booster() : m_connection(NULL), m_oldPriority(0), m_oldPriorityOk(false), - m_spaceAvailable(0) + m_spaceAvailable(0), + m_bootMode(false) {} Booster::~Booster() @@ -64,21 +65,20 @@ Booster::~Booster() m_appData = NULL; } -bool Booster::preload() -{ - return true; -} - void Booster::initialize(int initialArgc, char ** initialArgv, int newPipeFd[2], - int socketFd, SingleInstance * singleInstance) + int socketFd, SingleInstance * singleInstance, + bool newBootMode) { + m_bootMode = newBootMode; + setPipeFd(newPipeFd); // Drop priority (nice = 10) pushPriority(10); // Preload stuff - preload(); + if (!m_bootMode) + preload(); // Rename process to temporary booster process name, e.g. "booster-m" const char * tempArgv[] = {boosterTemporaryProcessName().c_str()}; @@ -139,6 +139,11 @@ void Booster::initialize(int initialArgc, char ** initialArgv, int newPipeFd[2], prctl(PR_SET_DUMPABLE, 1); } +bool Booster::bootMode() const +{ + return m_bootMode; +} + void Booster::sendDataToParent() { // Signal the parent process that it can create a new diff --git a/src/launcherlib/booster.h b/src/launcherlib/booster.h index 3b30de6..86491f7 100644 --- a/src/launcherlib/booster.h +++ b/src/launcherlib/booster.h @@ -68,15 +68,16 @@ public: /*! * \brief Initializes the booster process. + * \param initialArgc argc of the parent process. + * \param initialArgv argv of the parent process. + * \param pipefd pipe used to communicate with the parent process. + * \param socketFd File socket used to get commands from the invoker. + * \param singleInstance Pointer to a valid SingleInstance object. + * \param bootMode Booster-specific preloads are not executed if true. */ virtual void initialize(int initialArgc, char ** initialArgv, int pipefd[2], - int socketFd, SingleInstance * singleInstance); - - /*! - * \brief Preload libraries. - * Override in the custom Booster. - */ - virtual bool preload(); + int socketFd, SingleInstance * singleInstance, + bool bootMode); /*! * \brief Run the application to be invoked. @@ -141,17 +142,21 @@ public: * \brief Return the communication socket used by a Booster. * This method returns the socket used between invoker and the Booster. * (common to all Boosters of the type). Override in the custom Booster. - * \return Path to the socket file + * \return Path to the socket file. */ virtual const string & socketId() const = 0; -protected: + //! Return true, if in boot mode. + bool bootMode() const; - //! Set nice value and store the old priority. Return true on success. - bool pushPriority(int nice); +protected: - //! Restore the old priority stored by the previous successful setPriority(). - bool popPriority(); + /*! + * \brief Preload libraries / initialize cache etc. + * Called from initialize if not in the boot mode. + * Re-implement in the custom Booster. + */ + virtual bool preload() = 0; /*! * \brief Wait for connection from invoker and read the input. @@ -163,6 +168,12 @@ protected: */ virtual bool receiveDataFromInvoker(int socketFd); + //! Set nice value and store the old priority. Return true on success. + bool pushPriority(int nice); + + //! Restore the old priority stored by the previous successful setPriority(). + bool popPriority(); + //! Sets pipe fd's used to communicate with the parent process void setPipeFd(int pipeFd[2]); @@ -209,6 +220,9 @@ private: //! Original space available for arguments int m_spaceAvailable; + //! True, if being run in boot mode. + bool m_bootMode; + #ifdef HAVE_CREDS //! filter out invoker-specific credentials from boosted application static void filterOutCreds(creds_t creds); diff --git a/src/launcherlib/daemon.cpp b/src/launcherlib/daemon.cpp index 53b9da6..37c33dd 100644 --- a/src/launcherlib/daemon.cpp +++ b/src/launcherlib/daemon.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -46,6 +45,7 @@ const int Daemon::m_boosterSleepTime = 2; Daemon::Daemon(int & argc, char * argv[]) : m_daemon(false), m_quiet(false), + m_bootMode(false), m_socketManager(new SocketManager), m_singleInstance(new SingleInstance) { @@ -69,9 +69,24 @@ Daemon::Daemon(int & argc, char * argv[]) : m_initialArgv = argv; m_initialArgc = argc; - if (pipe(m_pipefd) == -1) + if (pipe(m_boosterPipeFd) == -1) { - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Creating a pipe failed!\n"); + Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Creating a pipe for boosters failed!\n"); + } + + if (pipe(m_sigChldPipeFd) == -1) + { + Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Creating a pipe for SIGCHLD failed!\n"); + } + + if (pipe(m_sigTermPipeFd) == -1) + { + Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Creating a pipe for SIGTERM failed!\n"); + } + + if (pipe(m_sigUsr1PipeFd) == -1) + { + Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Creating a pipe for SIGUSR1 failed!\n"); } // Daemonize if desired @@ -181,71 +196,134 @@ void Daemon::run() // Main loop while (true) { - // Wait for something appearing in the pipe. There should first - // appear a character representing the type of a booster and then - // pid of the invoker process that communicated with that booster. - char msg; - ssize_t count = read(m_pipefd[0], static_cast(&msg), 1); - if (count) + // Variables used by the select call + fd_set rfds; + int ndfs = 0; + + // Init data for select + FD_ZERO(&rfds); + + FD_SET(m_boosterPipeFd[0], &rfds); + ndfs = std::max(ndfs, m_boosterPipeFd[0]); + + FD_SET(m_sigChldPipeFd[0], &rfds); + ndfs = std::max(ndfs, m_sigChldPipeFd[0]); + + FD_SET(m_sigTermPipeFd[0], &rfds); + ndfs = std::max(ndfs, m_sigTermPipeFd[0]); + + FD_SET(m_sigUsr1PipeFd[0], &rfds); + ndfs = std::max(ndfs, m_sigUsr1PipeFd[0]); + + char buffer; + + // Wait for something appearing in the pipes. + if (select(ndfs + 1, &rfds, NULL, NULL, NULL) > 0) { - // Read pid of peer invoker - pid_t invokerPid; - count = read(m_pipefd[0], static_cast(&invokerPid), sizeof(pid_t)); + Logger::logDebug("select done."); - if (count < static_cast(sizeof(pid_t))) + // Check if a booster died + if (FD_ISSET(m_boosterPipeFd[0], &rfds)) { - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: pipe connection with booster failed"); + Logger::logDebug("FD_ISSET(m_boosterPipeFd[0])"); + readFromBoosterPipe(m_boosterPipeFd[0]); } - else + + // Check if we got SIGCHLD + if (FD_ISSET(m_sigChldPipeFd[0], &rfds)) { - Logger::logDebug("Daemon: invoker's pid: %d \n", invokerPid); + Logger::logDebug("FD_ISSET(m_sigChldPipeFd[0])"); + read(m_sigChldPipeFd[0], &buffer, 1); + reapZombies(); } - if (invokerPid != 0) + // Check if we got SIGTERM + if (FD_ISSET(m_sigTermPipeFd[0], &rfds)) { - // Store booster - invoker pid pair - pid_t boosterPid = boosterPidForType(msg); - if (boosterPid) - { - m_boosterPidToInvokerPid[boosterPid] = invokerPid; - } + Logger::logDebug("FD_ISSET(m_sigTermPipeFd[0])"); + read(m_sigTermPipeFd[0], &buffer, 1); + exit(EXIT_SUCCESS); } - // Read booster respawn delay - int delay; - count = read(m_pipefd[0], static_cast(&delay), sizeof(int)); - - if (count < static_cast(sizeof(int))) + // Check if we got SIGUSR1 + if (FD_ISSET(m_sigUsr1PipeFd[0], &rfds)) { - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: pipe connection with booster failed"); + Logger::logDebug("FD_ISSET(m_sigUsr1PipeFd[0])"); + read(m_sigUsr1PipeFd[0], &buffer, 1); + enterNormalMode(); } - else + } + } +} + +void Daemon::readFromBoosterPipe(int fd) +{ + // There should first appear a character representing the type of a + // booster and then pid of the invoker process that communicated with + // that booster. + char msg; + ssize_t count = read(fd, static_cast(&msg), 1); + if (count) + { + // Read pid of peer invoker + pid_t invokerPid; + count = read(fd, static_cast(&invokerPid), sizeof(pid_t)); + + if (count < static_cast(sizeof(pid_t))) + { + Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: pipe connection with booster failed"); + } + else + { + Logger::logDebug("Daemon: invoker's pid: %d \n", invokerPid); + } + + if (invokerPid != 0) + { + // Store booster - invoker pid pair + pid_t boosterPid = boosterPidForType(msg); + if (boosterPid) { - Logger::logDebug("Daemon: respawn delay: %d \n", delay); + m_boosterPidToInvokerPid[boosterPid] = invokerPid; } + } - // Fork a new booster of the given type - - // 2nd param guarantees some time for the just launched application - // to start up before forking new booster. Not doing this would - // slow down the start-up significantly on single core CPUs. + // Read booster respawn delay + int delay; + count = read(fd, static_cast(&delay), sizeof(int)); - forkBooster(msg, delay); + if (count < static_cast(sizeof(int))) + { + Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: pipe connection with booster failed"); } else { - Logger::logWarning("Daemon: Nothing read from the pipe\n"); + Logger::logDebug("Daemon: respawn delay received: %d \n", delay); } + + // Fork a new booster of the given type + + // 2nd param guarantees some time for the just launched application + // to start up before forking new booster. Not doing this would + // slow down the start-up significantly on single core CPUs. + + forkBooster(msg, delay); + } + else + { + Logger::logWarning("Daemon: Nothing read from the pipe\n"); } } -void Daemon::killProcess(pid_t pid) const +void Daemon::killProcess(pid_t pid, int signal) const { if (pid) { - if (kill(pid, SIGKILL) != 0) + Logger::logDebug("Daemon: Killing pid %d with %d", pid, signal); + if (kill(pid, signal) != 0) { - Logger::logError("Daemon: Failed to kill %d: %s\n", pid, strerror(errno)); + Logger::logError("Daemon: Failed to kill %d: %s\n", + pid, strerror(errno)); } } } @@ -273,8 +351,8 @@ void Daemon::loadSingleInstancePlugin() void Daemon::loadBoosterPlugins() { - const char* PATTERN = "lib*booster.so"; - const int BUF_LEN = 256; + const char* PATTERN = "lib*booster.so"; + const unsigned int BUF_LEN = 256; if (strlen(PATTERN) + strlen(BOOSTER_PLUGIN_DIR) + 2 > BUF_LEN) { @@ -322,6 +400,9 @@ void Daemon::loadBoosterPlugins() void Daemon::forkBooster(char type, int sleepTime) { + // Invalidate current booster pid for the given type + setPidToBooster(type, 0); + // Fork a new process pid_t newPid = fork(); @@ -333,12 +414,25 @@ void Daemon::forkBooster(char type, int sleepTime) // Reset used signal handlers signal(SIGCHLD, SIG_DFL); signal(SIGTERM, SIG_DFL); + signal(SIGUSR1, SIG_DFL); // Will get this signal if applauncherd dies prctl(PR_SET_PDEATHSIG, SIGHUP); - // Close unused read end - close(m_pipefd[0]); + // Close unused read end of the booster pipe + close(m_boosterPipeFd[0]); + + // Close SIGCHLD pipe + close(m_sigChldPipeFd[0]); + close(m_sigChldPipeFd[1]); + + // Close SIGTERM pipe + close(m_sigTermPipeFd[0]); + close(m_sigTermPipeFd[1]); + + // Close SIGUSR1 pipe + close(m_sigUsr1PipeFd[0]); + close(m_sigUsr1PipeFd[1]); // Close unused sockets inherited from daemon closeUnusedSockets(type); @@ -352,7 +446,8 @@ void Daemon::forkBooster(char type, int sleepTime) // Guarantee some time for the just launched application to // start up before forking new booster if needed. - if (sleepTime) + // Not done if in the boot mode. + if (!m_bootMode && sleepTime) sleep(sleepTime); Logger::logDebug("Daemon: Running a new Booster of type '%c'", type); @@ -362,9 +457,9 @@ void Daemon::forkBooster(char type, int sleepTime) if (booster) { // Initialize and wait for commands from invoker - booster->initialize(m_initialArgc, m_initialArgv, m_pipefd, + booster->initialize(m_initialArgc, m_initialArgv, m_boosterPipeFd, m_socketManager->findSocket(booster->socketId().c_str()), - m_singleInstance); + m_singleInstance, m_bootMode); // Run the current Booster booster->run(m_socketManager); @@ -543,9 +638,9 @@ void Daemon::daemonize() // Redirect standard file descriptors to /dev/null // Close new file descriptors - const int new_stdin = open("/dev/null", O_RDONLY); + const int new_stdin = open("/dev/null", O_RDONLY); if (new_stdin != -1) { - dup2(new_stdin, STDIN_FILENO); + dup2(new_stdin, STDIN_FILENO); close(new_stdin); } @@ -566,17 +661,67 @@ void Daemon::parseArgs(const ArgVect & args) { for (ArgVect::const_iterator i(args.begin()); i != args.end(); i++) { - if ((*i) == "--daemon") + if ((*i) == "--daemon" || (*i) == "-d") { m_daemon = true; } - else if ((*i) == "--quiet") + else if ((*i) == "--debug") + { + Logger::setDebugMode(true); + } + else if ((*i) == "--quiet" || (*i) == "-q") { m_quiet = true; } + else if ((*i) == "--boot-mode" || (*i) == "-b") + { + Logger::logInfo("Daemon: Boot mode set."); + m_bootMode = true; + } } } +int Daemon::sigChldPipeFd() const +{ + return m_sigChldPipeFd[1]; +} + +int Daemon::sigTermPipeFd() const +{ + return m_sigTermPipeFd[1]; +} + +int Daemon::sigUsr1PipeFd() const +{ + return m_sigUsr1PipeFd[1]; +} + +void Daemon::enterNormalMode() +{ + if (m_bootMode) + { + m_bootMode = false; + + // Kill current boosters + killBoosters(); + + Logger::logInfo("Daemon: Exited boot mode."); + } +} + +void Daemon::killBoosters() +{ + TypeMap::iterator iter(m_boosterTypeToPid.begin()); + while (iter != m_boosterTypeToPid.end()) + { + killProcess(iter->second, SIGTERM); + iter++; + } + + // NOTE!!: m_boosterTypeToPid must not be cleared + // in order to automatically start new boosters. +} + Daemon::~Daemon() { delete m_socketManager; diff --git a/src/launcherlib/daemon.h b/src/launcherlib/daemon.h index 5167ca1..a539ea9 100644 --- a/src/launcherlib/daemon.h +++ b/src/launcherlib/daemon.h @@ -37,6 +37,8 @@ using std::vector; using std::map; +#include + class Booster; class SocketManager; class SingleInstance; @@ -88,6 +90,15 @@ public: //! Unlock file (lock is not needed in boosters) static void unlock(); + //! Get fd to write when SIGCHLD arrives + int sigChldPipeFd() const; + + //! Get fd to write when SIGTERM arrives + int sigTermPipeFd() const; + + //! Get fd to write when SIGUSR1 arrives + int sigUsr1PipeFd() const; + private: //! Disable copy-constructor @@ -118,8 +129,8 @@ private: //! Don't use console for output void consoleQuiet(); - //! Kill given pid with SIGKILL - void killProcess(pid_t pid) const; + //! Kill given pid with SIGKILL by default + void killProcess(pid_t pid, int signal = SIGKILL) const; //! Load (dlopen()) booster plugins void loadBoosterPlugins(); @@ -139,12 +150,29 @@ private: //! Close all sockets NOT used by the given booster type. void closeUnusedSockets(char type); - //! Daemonize flag + //! Read and process data from a booster pipe + void readFromBoosterPipe(int fd); + + //! Enter normal mode (restart boosters with cache enabled) + void enterNormalMode(); + + //! Kill all active boosters with -9 + void killBoosters(); + + //! Daemonize flag (--fork). Daemon forks if true. bool m_daemon; - //! Debug print flag + //! Debug print flag (--quiet). Daemon closes fd's 0 - 2 if true. bool m_quiet; + /*! Flag indicating boot mode (--boot-mode). If true, then: + * - Caches won't be initialized. + * - Booster respwan delay is 0. + * + * Normal mode is activated by firing SIGUSR1. + */ + bool m_bootMode; + //! Vector of current child PID's typedef vector PidVect; PidVect m_children; @@ -157,8 +185,18 @@ private: typedef map TypeMap; TypeMap m_boosterTypeToPid; - //! Pipe used to tell the parent that a new booster is needed - int m_pipefd[2]; + //! Pipe used to tell the parent that a new booster is needed + + //! some parameters. + int m_boosterPipeFd[2]; + + //! Pipe used to safely catch SIGCHLD + int m_sigChldPipeFd[2]; + + //! Pipe used to safely catch SIGTERM + int m_sigTermPipeFd[2]; + + //! Pipe used to safely catch SIGUSR1 + int m_sigUsr1PipeFd[2]; //! Argument vector initially given to the launcher process int m_initialArgc; diff --git a/src/launcherlib/logger.cpp b/src/launcherlib/logger.cpp index ef84baf..7f1fd24 100644 --- a/src/launcherlib/logger.cpp +++ b/src/launcherlib/logger.cpp @@ -26,7 +26,7 @@ bool Logger::m_isOpened = false; -bool Logger::m_echoMode = false; +bool Logger::m_debugMode = false; void Logger::openLog(const char * progName) { @@ -48,8 +48,8 @@ void Logger::writeLog(const int priority, const char * format, va_list ap) { if (Logger::m_isOpened) { - // In echo mode everything is printed also to stdout - if (m_echoMode) + // In debug mode everything is printed also to stdout + if (m_debugMode) { vprintf(format, ap); printf("\n"); @@ -62,14 +62,13 @@ void Logger::writeLog(const int priority, const char * format, va_list ap) void Logger::logDebug(const char * format, ...) { -#ifndef DEBUG_LOGGING_DISABLED - va_list(ap); - va_start(ap, format); - writeLog(LOG_DEBUG, format, ap); - va_end(ap); -#else - (void)format; -#endif + if (m_debugMode) + { + va_list(ap); + va_start(ap, format); + writeLog(LOG_DEBUG, format, ap); + va_end(ap); + } } void Logger::logInfo(const char * format, ...) @@ -107,8 +106,8 @@ void Logger::logErrorAndDie(int code, const char * format, ...) _exit(code); } -void Logger::setEchoMode(bool enable) +void Logger::setDebugMode(bool enable) { - Logger::m_echoMode = enable; + Logger::m_debugMode = enable; } diff --git a/src/launcherlib/logger.h b/src/launcherlib/logger.h index a075ab7..69b1be6 100644 --- a/src/launcherlib/logger.h +++ b/src/launcherlib/logger.h @@ -42,9 +42,9 @@ public: */ static void closeLog(); - /*! - * \brief Log a notice to the system message logger + * \brief Log a debug to the system message logger. + * Effective only if Logger::setDebugMode(true) called; * \param format String identical to a printf format string * \param additionalArgs Depending on the format string, the function may expect a * sequence of additional arguments, each containing one value to be inserted @@ -52,7 +52,6 @@ public: */ static void logDebug(const char * format, ...); - /*! * \brief Log an error to the system message logger * \param format String identical to a printf format string @@ -62,7 +61,6 @@ public: */ static void logError(const char * format, ...); - /*! * \brief Log a warning to the system message logger * \param format String identical to a printf format string @@ -72,7 +70,6 @@ public: */ static void logWarning(const char * format, ...); - /*! * \brief Log a piece of information to the system message logger * \param format String identical to a printf format string @@ -91,19 +88,20 @@ public: */ static void logErrorAndDie(int code, const char * format, ...); - /*! - * \brief Forces Logger to echo everything to stdout if set to true. + * \brief Forces Logger to log everything and echo to stdout if set to true. */ - static void setEchoMode(bool enable); + static void setDebugMode(bool enable); private: static void writeLog(const int priority, const char * format, va_list ap); + //! True if the log is open static bool m_isOpened; - //! Echo everything to stdout if true - static bool m_echoMode; + + //! Echo everything including debug messages to stdout if true + static bool m_debugMode; }; #endif // LOGGER_H diff --git a/src/launcherlib/main.cpp b/src/launcherlib/main.cpp index b8a0799..549da10 100644 --- a/src/launcherlib/main.cpp +++ b/src/launcherlib/main.cpp @@ -28,24 +28,30 @@ #define DECL_EXPORT extern "C" __attribute__ ((__visibility__("default"))) -//! Signal handler to reap zombie processes -void reapZombies(int) +int g_sigChldPipeFd = -1; +int g_sigTermPipeFd = -1; +int g_sigUsr1PipeFd = -1; + +char g_dummyPipeData = 0; + +static void sigChldHandler(int) { - if (Daemon::instance()) - { - Daemon::instance()->reapZombies(); - } + write(g_sigChldPipeFd, &g_dummyPipeData, 1); +} + +static void sigTermHandler(int) +{ + write(g_sigTermPipeFd, &g_dummyPipeData, 1); } -void exitLauncher(int) +static void sigUsr1Handler(int) { - exit(0); + write(g_sigUsr1PipeFd, &g_dummyPipeData, 1); } //! Main function DECL_EXPORT int main(int argc, char * argv[]) { - // Open the log Logger::openLog(PROG_NAME_LAUNCHER); Logger::logDebug("%s starting..", PROG_NAME_LAUNCHER); @@ -56,13 +62,19 @@ DECL_EXPORT int main(int argc, char * argv[]) Logger::logErrorAndDie(EXIT_FAILURE, "%s is already running \n", PROG_NAME_LAUNCHER); } - // Install signal handlers - signal(SIGCHLD, reapZombies); - signal(SIGTERM, exitLauncher); - // Create main daemon instance Daemon myDaemon(argc, argv); + // Get fd's for signal pipes. + g_sigChldPipeFd = myDaemon.sigChldPipeFd(); + g_sigTermPipeFd = myDaemon.sigTermPipeFd(); + g_sigUsr1PipeFd = myDaemon.sigUsr1PipeFd(); + + // Install signal handlers + signal(SIGCHLD, sigChldHandler); // reap zombies + signal(SIGTERM, sigTermHandler); // exit launcher + signal(SIGUSR1, sigUsr1Handler); // restore normal mode + // Run the main loop myDaemon.run(); @@ -71,4 +83,3 @@ DECL_EXPORT int main(int argc, char * argv[]) return EXIT_SUCCESS; } - diff --git a/src/mbooster/mbooster.cpp b/src/mbooster/mbooster.cpp index 7e8c565..2a94adf 100644 --- a/src/mbooster/mbooster.cpp +++ b/src/mbooster/mbooster.cpp @@ -41,6 +41,7 @@ bool MBooster::preload() // an MApplication) MComponentCache::populateForMApplication(); #endif + return true; } @@ -66,26 +67,36 @@ char MBooster::type() bool MBooster::receiveDataFromInvoker(int socketFd) { - // Setup the conversation channel with the invoker. - setConnection(new Connection(socketFd)); - - EventHandler handler(this); - handler.runEventLoop(); + // Use the default implementation if in boot mode + // (it won't require QApplication running). - // Receive application data from the invoker - if(!connection()->receiveApplicationData(appData())) + if (bootMode()) { - connection()->close(); - return false; + return Booster::receiveDataFromInvoker(socketFd); } - - // Close the connection if exit status doesn't need - // to be sent back to invoker - if (!connection()->isReportAppExitStatusNeeded()) + else { - connection()->close(); - } + // Setup the conversation channel with the invoker. + setConnection(new Connection(socketFd)); - return true; + EventHandler handler(this); + handler.runEventLoop(); + + // Receive application data from the invoker + if(!connection()->receiveApplicationData(appData())) + { + connection()->close(); + return false; + } + + // Close the connection if exit status doesn't need + // to be sent back to invoker + if (!connection()->isReportAppExitStatusNeeded()) + { + connection()->close(); + } + + return true; + } } diff --git a/src/mbooster/mbooster.h b/src/mbooster/mbooster.h index b60bf79..af72cee 100644 --- a/src/mbooster/mbooster.h +++ b/src/mbooster/mbooster.h @@ -47,9 +47,6 @@ public: //! \brief Destructor virtual ~MBooster() {} - //! \reimp - virtual bool preload(); - /*! * \brief Return the socket name common to all MBooster objects. * \return Path to the socket file. @@ -77,6 +74,9 @@ public: protected: + //! \reimp + virtual bool preload(); + //! \reimp virtual bool receiveDataFromInvoker(int socketFd); diff --git a/src/qtbooster/qtbooster.h b/src/qtbooster/qtbooster.h index 4e78b51..cf1b9ae 100644 --- a/src/qtbooster/qtbooster.h +++ b/src/qtbooster/qtbooster.h @@ -58,11 +58,11 @@ public: */ static char type(); +protected: + //! \reimp virtual bool preload(); -protected: - //! \reimp virtual const string & socketId() const; diff --git a/src/scripts/applauncherd b/src/scripts/applauncherd index 0706ac4..4e67aef 100755 --- a/src/scripts/applauncherd +++ b/src/scripts/applauncherd @@ -6,5 +6,5 @@ # If the length of the application name with parameters is longer than space # available, parameters will be cut off. The main function will still always # get the complete argument list. -exec /usr/bin/applauncherd.bin " " +exec /usr/bin/applauncherd.bin $@ " " diff --git a/tests/Common/unittests/ut_booster/ut_booster.cpp b/tests/Common/unittests/ut_booster/ut_booster.cpp index b6e3a31..7c77e42 100644 --- a/tests/Common/unittests/ut_booster/ut_booster.cpp +++ b/tests/Common/unittests/ut_booster/ut_booster.cpp @@ -30,6 +30,9 @@ public: const std::string & socketId() const; const std::string & boosterTemporaryProcessName() const; +protected: + bool preload(); + private: const string m_socketId; const string m_temporaryProcessName; @@ -45,6 +48,11 @@ char MyBooster::boosterType() const return 'x'; } +bool MyBooster::preload() +{ + return true; +} + const std::string & MyBooster::boosterTemporaryProcessName() const { return m_temporaryProcessName;