diff --git a/src/invoker/invoker.c b/src/invoker/invoker.c index 0d006a3..896c5a3 100644 --- a/src/invoker/invoker.c +++ b/src/invoker/invoker.c @@ -60,16 +60,16 @@ enum APP_TYPE { M_APP, QT_APP, WRT_APP, UNKNOWN_APP }; extern char ** environ; // pid of the invoked process -static pid_t invoked_pid = -1; +static pid_t g_invoked_pid = -1; static void sigs_restore(void); // Forwards Unix signals from invoker to the invoked process static void sig_forwarder(int sig) { - if (invoked_pid >= 0) + if (g_invoked_pid >= 0) { - if (kill(invoked_pid, sig) != 0) + if (kill(g_invoked_pid, sig) != 0) { report(report_error, "Can't send signal to application: %s \n", strerror(errno)); } @@ -445,6 +445,88 @@ static unsigned int get_delay(char *delay_arg) return delay; } +// Fallback for invoke if connection to the launcher is broken. +// Forks a new process if wait term is not used. +void invoke_fallback(char **prog_argv, char *prog_name, bool wait_term) +{ + // Connection with launcher is broken, + // try to launch application via execve + warning("Connection with launcher process is broken. \n"); + warning("Trying to start application as a binary executable without launcher...\n"); + + // Fork if wait_term not set + if(!wait_term) + { + // Fork a new process + pid_t newPid = fork(); + + if (newPid == -1) + { + report(report_error, "Invoker failed to fork"); + exit(EXIT_FAILURE); + } + else if (newPid != 0) /* parent process */ + { + return; + } + } + + // Exec the process image + execve(prog_name, prog_argv, environ); + perror("execve"); /* execve() only returns on error */ + exit(EXIT_FAILURE); +} + +// "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 status = 0; + + // Get process priority + errno = 0; + int prog_prio = getpriority(PRIO_PROCESS, 0); + if (errno && prog_prio < 0) + { + prog_prio = 0; + } + + // Connection with launcher process is established, + // send the data. + invoker_send_magic(fd, magic_options); + invoker_send_name(fd, prog_argv[0]); + invoker_send_exec(fd, prog_name); + invoker_send_args(fd, prog_argc, prog_argv); + invoker_send_prio(fd, prog_prio); + invoker_send_ids(fd, getuid(), getgid()); + invoker_send_io(fd); + invoker_send_env(fd); + invoker_send_end(fd); + + if (prog_name) + { + free(prog_name); + } + + // Wait for launched process to exit + if (wait_term) + { + g_invoked_pid = invoker_recv_pid(fd); + debug("Booster's pid is %d \n ", g_invoked_pid); + + // Forward signals to the invoked process + sigs_init(); + + // Wait for exit status from the invoked application + status = invoker_recv_exit(fd); + + // Restore default signal handlers + sigs_restore(); + } + + return status; +} + // 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) @@ -453,79 +535,18 @@ static int invoke(int prog_argc, char **prog_argv, char *prog_name, if (prog_name && prog_argv) { - // Get process priority - errno = 0; - int prog_prio = getpriority(PRIO_PROCESS, 0); - if (errno && prog_prio < 0) - { - prog_prio = 0; - } - // This is a fallback if connection with the launcher // process is broken int fd = invoker_init(app_type); if (fd == -1) { - // Connection with launcher is broken, - // try to launch application via execve - warning("Connection with launcher process is broken. \n"); - warning("Trying to start application as a binary executable without launcher...\n"); - - if(!wait_term) - { - // Fork a new process - pid_t newPid = fork(); - - if (newPid == -1) - { - report(report_error, "Invoker failed to fork"); - exit(EXIT_FAILURE); - } - if (newPid != 0) /* parent process */ - { - return 0; - } - } - - execve(prog_name, prog_argv, environ); - perror("execve"); /* execve() only returns on error */ - exit(EXIT_FAILURE); + invoke_fallback(prog_argv, prog_name, wait_term); } + // "normal" invoke through a socket connetion else { - // Connection with launcher process is established, - // send the data. - invoker_send_magic(fd, magic_options); - invoker_send_name(fd, prog_argv[0]); - invoker_send_exec(fd, prog_name); - invoker_send_args(fd, prog_argc, prog_argv); - invoker_send_prio(fd, prog_prio); - invoker_send_ids(fd, getuid(), getgid()); - invoker_send_io(fd); - invoker_send_env(fd); - invoker_send_end(fd); - - if (prog_name) - { - free(prog_name); - } - - // Wait for launched process to exit - if (wait_term) - { - invoked_pid = invoker_recv_pid(fd); - debug("Booster's pid is %d \n ", invoked_pid); - - // Forward signals to the invoked process - sigs_init(); - - // Wait for exit status from the invoked application - status = invoker_recv_exit(fd); - - // Restore default signal handlers - sigs_restore(); - } - + status = invoke_remote(fd, prog_argc, prog_argv, prog_name, + magic_options, wait_term); close(fd); } } @@ -565,6 +586,7 @@ int main(int argc, char *argv[]) }; // Parse options + // TODO: Move to a function int opt; while ((opt = getopt_long(argc, argv, "hcwd:t:", longopts, NULL)) != -1) {