// Forwards Unix signals from invoker to the invoked process static void sig_forwarder(int sig) { if (g_invoked_pid >= 0) { if (kill(g_invoked_pid, sig) != 0) { if (sig == SIGTERM && errno == ESRCH) { report(report_info, "Can't send signal SIGTERM to application [%i] " "because application is already terminated. \n", g_invoked_pid); } else { report(report_error, "Can't send signal %i to application [%i]: %s \n", sig, g_invoked_pid, strerror(errno)); } } // Restore signal handlers sigs_restore(); // Write signal number to the self-pipe char signal_id = (char) sig; write(g_signal_pipe[1], &signal_id, 1); // Send the signal to itself using the default handler raise(sig); #ifdef WITH_COVERAGE __gcov_flush(); #endif } }
// Forwards Unix signals from invoker to the invoked process static void sig_forwarder(int sig) { if (g_invoked_pid >= 0) { if (kill(g_invoked_pid, sig) != 0) { report(report_error, "Can't send signal to application: %s \n", strerror(errno)); } sigs_restore(); raise(sig); } }
// "normal" invoke through a socket connection int invoke_remote(int fd, int prog_argc, char **prog_argv, char *prog_name, uint32_t magic_options, bool wait_term, unsigned int respawn_delay) { 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_delay(fd, respawn_delay); 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; }
static int wait_for_launched_process_to_exit(int socket_fd, bool wait_term) { int status = 0; // Wait for launched process to exit if (wait_term) { // coverity[tainted_string_return_content] g_invoked_pid = invoker_recv_pid(socket_fd); debug("Booster's pid is %d \n ", g_invoked_pid); // Forward UNIX signals to the invoked process sigs_init(); while(1) { // Setup things for select() fd_set readfds; int ndfs = 0; FD_ZERO(&readfds); FD_SET(socket_fd, &readfds); ndfs = (socket_fd > ndfs) ? socket_fd : ndfs; // sig_forwarder() handles signals. // We only have to receive those here. FD_SET(g_signal_pipe[0], &readfds); ndfs = (g_signal_pipe[0] > ndfs) ? g_signal_pipe[0] : ndfs; // Wait for something appearing in the pipes. if (select(ndfs + 1, &readfds, NULL, NULL, NULL) > 0) { // Check if an exit status from the invoked application if (FD_ISSET(socket_fd, &readfds)) { bool res = invoker_recv_exit(socket_fd, &status); if (!res) { // Because we are here, applauncherd.bin must be dead. // Now we check if the invoked process is also dead // and if not, we will kill it. char filename[50]; snprintf(filename, sizeof(filename), "/proc/%d/cmdline", g_invoked_pid); // Open filename for reading only int fd = open(filename, O_RDONLY); if (fd != -1) { // Application is still running close(fd); // Send a signal to kill the application too and exit. // Sleep for some time to give // the new applauncherd some time to load its boosters and // the restart of g_invoked_pid succeeds. sleep(10); kill(g_invoked_pid, SIGKILL); raise(SIGKILL); } else { // connection to application was lost status = EXIT_FAILURE; } } break; } // Check if we got a UNIX signal. else if (FD_ISSET(g_signal_pipe[0], &readfds)) { // Clean up the pipe char signal_id; read(g_signal_pipe[0], &signal_id, sizeof(signal_id)); // Set signals forwarding to the invoked process again // (they were reset by the signal forwarder). sigs_init(); } } } // Restore default signal handlers sigs_restore(); } return status; }