diff --git a/src/common/protocol.h b/src/common/protocol.h index 46dac00..b188454 100644 --- a/src/common/protocol.h +++ b/src/common/protocol.h @@ -33,6 +33,7 @@ const uint32_t INVOKER_MSG_EXEC = 0xe8ec0000; const uint32_t INVOKER_MSG_ARGS = 0xa4650000; const uint32_t INVOKER_MSG_ENV = 0xe5710000; const uint32_t INVOKER_MSG_PRIO = 0xa1ce0000; +const uint32_t INVOKER_MSG_DELAY = 0xb2de0012; const uint32_t INVOKER_MSG_IDS = 0xb2df4000; const uint32_t INVOKER_MSG_IO = 0x10fd0000; const uint32_t INVOKER_MSG_END = 0xdead0000; diff --git a/src/invoker/invoker.c b/src/invoker/invoker.c index 896c5a3..8fe12e7 100644 --- a/src/invoker/invoker.c +++ b/src/invoker/invoker.c @@ -49,6 +49,9 @@ // Delay before exit static const int DEFAULT_DELAY = 0; +static const unsigned int RESPAWN_DELAY = 2; +static const unsigned int MAX_RESPAWN_DELAY = 10; + // Enumeration of possible application types: // M_APP : MeeGo Touch application // QT_APP : Qt/generic application @@ -321,6 +324,18 @@ static bool invoker_send_prio(int fd, int prio) return true; } +// Sends booster respawn delay +static bool invoker_send_delay(int fd, int delay) +{ + // Send action. + invoke_send_msg(fd, INVOKER_MSG_DELAY); + invoke_send_msg(fd, delay); + + invoke_recv_ack(fd); + + return true; +} + // Sends UID and GID static bool invoker_send_ids(int fd, int uid, int gid) { @@ -416,16 +431,17 @@ static void usage(int status) "Options:\n" " -c, --creds Print Aegis security credentials (if enabled).\n" " -d, --delay SECS After invoking sleep for SECS seconds (default %d).\n" + " -r, --respawn SECS After invoking respawn new booster after SECS seconds (default %d, max %d).\n" " -w, --wait-term Wait for launched process to terminate.\n" " -h, --help Print this help message.\n\n" "Example: %s --type=m /usr/bin/helloworld\n\n", - PROG_NAME_INVOKER, DEFAULT_DELAY, PROG_NAME_INVOKER); + PROG_NAME_INVOKER, DEFAULT_DELAY, RESPAWN_DELAY, MAX_RESPAWN_DELAY, PROG_NAME_INVOKER); exit(status); } // Return delay as integer -static unsigned int get_delay(char *delay_arg) +static unsigned int get_delay(char *delay_arg, char *param_name) { unsigned int delay = DEFAULT_DELAY; @@ -437,7 +453,7 @@ static unsigned int get_delay(char *delay_arg) // Check for various possible errors if ((errno == ERANGE && delay == ULONG_MAX) || delay == 0) { - report(report_error, "Wrong value of delay parameter: %s\n", delay_arg); + report(report_error, "Wrong value of %s parameter: %s\n", param_name, delay_arg); usage(1); } } @@ -479,7 +495,7 @@ void invoke_fallback(char **prog_argv, char *prog_name, bool wait_term) // "normal" invoke through a socket connection int invoke_remote(int fd, int prog_argc, char **prog_argv, char *prog_name, - int magic_options, bool wait_term) + int magic_options, bool wait_term, unsigned int respawn_delay) { int status = 0; @@ -498,6 +514,7 @@ int invoke_remote(int fd, int prog_argc, char **prog_argv, char *prog_name, invoker_send_exec(fd, prog_name); invoker_send_args(fd, prog_argc, prog_argv); invoker_send_prio(fd, prog_prio); + invoker_send_delay(fd, respawn_delay); invoker_send_ids(fd, getuid(), getgid()); invoker_send_io(fd); invoker_send_env(fd); @@ -529,7 +546,7 @@ int invoke_remote(int fd, int prog_argc, char **prog_argv, char *prog_name, // Invokes the given application static int invoke(int prog_argc, char **prog_argv, char *prog_name, - enum APP_TYPE app_type, int magic_options, bool wait_term) + enum APP_TYPE app_type, int magic_options, bool wait_term, unsigned int respawn_delay) { int status = 0; @@ -546,7 +563,7 @@ static int invoke(int prog_argc, char **prog_argv, char *prog_name, else { status = invoke_remote(fd, prog_argc, prog_argv, prog_name, - magic_options, wait_term); + magic_options, wait_term, respawn_delay); close(fd); } } @@ -561,6 +578,7 @@ int main(int argc, char *argv[]) int magic_options = 0; bool wait_term = false; unsigned int delay = DEFAULT_DELAY; + unsigned int respawn_delay = RESPAWN_DELAY; char **prog_argv = NULL; char *prog_name = NULL; @@ -577,18 +595,19 @@ int main(int argc, char *argv[]) // Options recognized struct option longopts[] = { - {"help", no_argument, NULL, 'h'}, - {"creds", no_argument, NULL, 'c'}, - {"wait-term", no_argument, NULL, 'w'}, - {"type", required_argument, NULL, 't'}, - {"delay", required_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {"creds", no_argument, NULL, 'c'}, + {"wait-term", no_argument, NULL, 'w'}, + {"type", required_argument, NULL, 't'}, + {"delay", required_argument, NULL, 'd'}, + {"respawn", required_argument, NULL, 'r'}, {0, 0, 0, 0} }; // Parse options // TODO: Move to a function int opt; - while ((opt = getopt_long(argc, argv, "hcwd:t:", longopts, NULL)) != -1) + while ((opt = getopt_long(argc, argv, "hcwd:t:r:", longopts, NULL)) != -1) { switch(opt) { @@ -620,7 +639,16 @@ int main(int argc, char *argv[]) break; case 'd': - delay = get_delay(optarg); + delay = get_delay(optarg, "delay"); + break; + + case 'r': + respawn_delay = get_delay(optarg, "respawn delay"); + if (respawn_delay > MAX_RESPAWN_DELAY) + { + report(report_error, "Booster respawn delay exceeds max possible time.\n"); + usage(1); + } break; case '?': @@ -664,7 +692,7 @@ int main(int argc, char *argv[]) // Send commands to the launcher daemon info("Invoking execution: '%s'\n", prog_name); - int ret_val = invoke(prog_argc, prog_argv, prog_name, app_type, magic_options, wait_term); + int ret_val = invoke(prog_argc, prog_argv, prog_name, app_type, magic_options, wait_term, respawn_delay); // Sleep for delay before exiting if (delay) diff --git a/src/launcher/appdata.cpp b/src/launcher/appdata.cpp index 3358ff2..3dd5272 100644 --- a/src/launcher/appdata.cpp +++ b/src/launcher/appdata.cpp @@ -30,6 +30,7 @@ AppData::AppData() : m_appName(""), m_fileName(""), m_prio(0), + m_delay(0), m_entry(NULL), m_ioDescriptors(), m_gid(0), @@ -99,6 +100,16 @@ int AppData::priority() const return m_prio; } +void AppData::setDelay(int newDelay) +{ + m_delay = newDelay; +} + +int AppData::delay() +{ + return m_delay; +} + void AppData::setEntry(entry_t newEntry) { m_entry = newEntry; diff --git a/src/launcher/appdata.h b/src/launcher/appdata.h index 8289fd9..6df955d 100644 --- a/src/launcher/appdata.h +++ b/src/launcher/appdata.h @@ -81,6 +81,12 @@ public: //! Return priority int priority() const; + //! Set booster respawn delay + void setDelay(int delay); + + //!Return respawn delay + int delay(); + //! Set entry point for the application void setEntry(entry_t entry); @@ -127,6 +133,7 @@ private: string m_appName; string m_fileName; int m_prio; + int m_delay; entry_t m_entry; vector m_ioDescriptors; gid_t m_gid; diff --git a/src/launcher/booster.cpp b/src/launcher/booster.cpp index 11bae21..b468f9f 100644 --- a/src/launcher/booster.cpp +++ b/src/launcher/booster.cpp @@ -96,8 +96,21 @@ void Booster::initialize(int initialArgc, char ** initialArgv, int newPipeFd[2]) Logger::logError("Booster: Couldn't send invoker's pid to launcher process\n"); } + // Send to the parent process booster respawn delay value + int delay = m_app.delay(); + ret = write(pipeFd(1), reinterpret_cast(&delay), sizeof(int)); + if (ret == -1) { + Logger::logError("Booster: Couldn't send respawn delay value to launcher process\n"); + } + // close pipe close(pipeFd(1)); + + // Don't care about fate of parent applauncherd process any more + prctl(PR_SET_PDEATHSIG, 0); + + // Set dumpable flag + prctl(PR_SET_DUMPABLE, 1); } bool Booster::readCommand() diff --git a/src/launcher/connection.cpp b/src/launcher/connection.cpp index 442315f..e7cea6b 100644 --- a/src/launcher/connection.cpp +++ b/src/launcher/connection.cpp @@ -42,6 +42,7 @@ Connection::Connection(const string socketId, bool testMode) : m_argc(0), m_argv(NULL), m_priority(0), + m_delay(0), m_sendPid(false) { m_io[0] = -1; @@ -365,6 +366,14 @@ bool Connection::receivePriority() return true; } +bool Connection::receiveDelay() +{ + recvMsg(&m_delay); + sendMsg(INVOKER_MSG_ACK); + + return true; +} + bool Connection::receiveIDs() { recvMsg(&m_uid); @@ -547,6 +556,9 @@ bool Connection::receiveActions() case INVOKER_MSG_PRIO: receivePriority(); break; + case INVOKER_MSG_DELAY: + receiveDelay(); + break; case INVOKER_MSG_IO: receiveIO(); break; @@ -584,6 +596,7 @@ bool Connection::receiveApplicationData(AppData & rApp) { rApp.setFileName(m_fileName); rApp.setPriority(m_priority); + rApp.setDelay(m_delay); rApp.setArgc(m_argc); rApp.setArgv(m_argv); rApp.setIODescriptors(vector(m_io, m_io + IO_DESCRIPTOR_COUNT)); diff --git a/src/launcher/connection.h b/src/launcher/connection.h index c8cf1e9..5cf12a1 100644 --- a/src/launcher/connection.h +++ b/src/launcher/connection.h @@ -142,6 +142,9 @@ private: //! Receive priority bool receivePriority(); + //! Receive booster respawn delay + bool receiveDelay(); + //! Send process pid bool sendPid(pid_t pid); @@ -171,6 +174,7 @@ private: const char ** m_argv; int m_io[IO_DESCRIPTOR_COUNT]; uint32_t m_priority; + uint32_t m_delay; bool m_sendPid; gid_t m_gid; uid_t m_uid; diff --git a/src/launcher/daemon.cpp b/src/launcher/daemon.cpp index 79953f1..eb7ab71 100644 --- a/src/launcher/daemon.cpp +++ b/src/launcher/daemon.cpp @@ -195,13 +195,26 @@ void Daemon::run() m_boosterPidToInvokerPid[BoosterFactory::getBoosterPidForType(msg)] = invokerPid; } + // Read booster respawn delay + int delay; + count = read(m_pipefd[0], reinterpret_cast(&delay), sizeof(int)); + + if (count < static_cast(sizeof(int))) + { + Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: pipe connection with booster failed"); + } + else + { + Logger::logInfo("Daemon: respawn delay: %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, m_boosterSleepTime); + forkBooster(msg, delay); } // It was from a monitor booster, that means that theme / language has // changed so we need to reset (kill) MBooster and WRTBooster. @@ -271,12 +284,6 @@ void Daemon::forkBooster(char type, int sleepTime) { booster->initialize(m_initialArgc, m_initialArgv, m_pipefd); - // Don't care about fate of parent applauncherd process any more - prctl(PR_SET_PDEATHSIG, 0); - - // Set dumpable flag - prctl(PR_SET_DUMPABLE, 1); - // Run the current Booster booster->run();