|
|
|
|
@ -80,7 +80,7 @@ static void sigs_restore(void);
|
|
|
|
|
static void sigs_init(void);
|
|
|
|
|
|
|
|
|
|
//! Pipe used to safely catch Unix signals
|
|
|
|
|
static int g_sigPipe[2];
|
|
|
|
|
static int g_signal_pipe[2];
|
|
|
|
|
|
|
|
|
|
// Forwards Unix signals from invoker to the invoked process
|
|
|
|
|
static void sig_forwarder(int sig)
|
|
|
|
|
@ -91,12 +91,15 @@ static void sig_forwarder(int sig)
|
|
|
|
|
{
|
|
|
|
|
report(report_error, "Can't send signal to application: %s \n", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Restore signal handlers
|
|
|
|
|
sigs_restore();
|
|
|
|
|
|
|
|
|
|
// Write signal number to the self-pipe
|
|
|
|
|
char signal_id = (char) sig;
|
|
|
|
|
write(g_sigPipe[1], &signal_id, 1);
|
|
|
|
|
write(g_signal_pipe[1], &signal_id, 1);
|
|
|
|
|
|
|
|
|
|
// send a signal itself for default handler
|
|
|
|
|
// Send the signal to itself using the default handler
|
|
|
|
|
raise(sig);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -483,136 +486,82 @@ static unsigned int get_delay(char *delay_arg, char *param_name,
|
|
|
|
|
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\n");
|
|
|
|
|
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,
|
|
|
|
|
uint32_t magic_options, bool wait_term, unsigned int respawn_delay,
|
|
|
|
|
char *splash_file, char *landscape_splash_file)
|
|
|
|
|
static int wait_for_launched_process_to_exit(int socket_fd, 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_delay(fd, respawn_delay);
|
|
|
|
|
invoker_send_ids(fd, getuid(), getgid());
|
|
|
|
|
if (( magic_options & INVOKER_MSG_MAGIC_OPTION_SPLASH_SCREEN ) != 0)
|
|
|
|
|
invoker_send_splash_file(fd, splash_file);
|
|
|
|
|
if (( magic_options & INVOKER_MSG_MAGIC_OPTION_LANDSCAPE_SPLASH_SCREEN ) != 0)
|
|
|
|
|
invoker_send_landscape_splash_file(fd, landscape_splash_file);
|
|
|
|
|
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);
|
|
|
|
|
g_invoked_pid = invoker_recv_pid(socket_fd);
|
|
|
|
|
debug("Booster's pid is %d \n ", g_invoked_pid);
|
|
|
|
|
|
|
|
|
|
// Forward signals to the invoked process
|
|
|
|
|
// 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(fd, &readfds);
|
|
|
|
|
ndfs = (fd > ndfs) ? fd : ndfs;
|
|
|
|
|
FD_SET(socket_fd, &readfds);
|
|
|
|
|
ndfs = (socket_fd > ndfs) ? socket_fd : ndfs;
|
|
|
|
|
|
|
|
|
|
FD_SET(g_sigPipe[0], &readfds);
|
|
|
|
|
ndfs = (fd > ndfs) ? fd : ndfs;
|
|
|
|
|
FD_SET(g_signal_pipe[0], &readfds);
|
|
|
|
|
ndfs = (socket_fd > ndfs) ? socket_fd : 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(fd, &readfds))
|
|
|
|
|
if (FD_ISSET(socket_fd, &readfds))
|
|
|
|
|
{
|
|
|
|
|
//check if we've got application exit status or process on the other side of socket just exited
|
|
|
|
|
|
|
|
|
|
// Check if we've got application exit status or if the process
|
|
|
|
|
// on the other side of socket just died / was killed.
|
|
|
|
|
// We check from /proc whether the launched program is still
|
|
|
|
|
// running.
|
|
|
|
|
char filename[50];
|
|
|
|
|
snprintf(filename, sizeof(filename), "/proc/%d/cmdline", g_invoked_pid);
|
|
|
|
|
|
|
|
|
|
//Open filename for reading only
|
|
|
|
|
fd = open(filename, O_RDONLY);
|
|
|
|
|
// Open filename for reading only
|
|
|
|
|
int fd = open(filename, O_RDONLY);
|
|
|
|
|
if (fd != -1)
|
|
|
|
|
{
|
|
|
|
|
// application is still running, so applauncherd is dead
|
|
|
|
|
// Application is still running, so applauncherd must be dead,
|
|
|
|
|
// because the blocking read on the socket returned.
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
|
|
// send a signal to kill application and exit
|
|
|
|
|
// Send a signal to kill the application too and exit.
|
|
|
|
|
// We must do this, because the invoker<->application
|
|
|
|
|
// mapping is lost. 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = invoker_recv_exit(fd);
|
|
|
|
|
status = invoker_recv_exit(socket_fd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// Check if an exit status from the invoked application
|
|
|
|
|
else if (FD_ISSET(g_sigPipe[0], &readfds))
|
|
|
|
|
// Check if we got a UNIX signal.
|
|
|
|
|
else if (FD_ISSET(g_signal_pipe[0], &readfds))
|
|
|
|
|
{
|
|
|
|
|
// clean up pipe
|
|
|
|
|
// Clean up the pipe
|
|
|
|
|
char signal_id;
|
|
|
|
|
read(g_sigPipe[0], &signal_id, sizeof(signal_id));
|
|
|
|
|
read(g_signal_pipe[0], &signal_id, sizeof(signal_id));
|
|
|
|
|
|
|
|
|
|
// set signals forwarding to the invoked process
|
|
|
|
|
// Set signals forwarding to the invoked process again
|
|
|
|
|
// (they were reset by the signal forwarder).
|
|
|
|
|
sigs_init();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Restore default signal handlers
|
|
|
|
|
sigs_restore();
|
|
|
|
|
}
|
|
|
|
|
@ -620,6 +569,45 @@ int invoke_remote(int fd, int prog_argc, char **prog_argv, char *prog_name,
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// "normal" invoke through a socket connection
|
|
|
|
|
static int invoke_remote(int socket_fd, int prog_argc, char **prog_argv, char *prog_name,
|
|
|
|
|
uint32_t magic_options, bool wait_term, unsigned int respawn_delay,
|
|
|
|
|
char *splash_file, char *landscape_splash_file)
|
|
|
|
|
{
|
|
|
|
|
// 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(socket_fd, magic_options);
|
|
|
|
|
invoker_send_name(socket_fd, prog_argv[0]);
|
|
|
|
|
invoker_send_exec(socket_fd, prog_name);
|
|
|
|
|
invoker_send_args(socket_fd, prog_argc, prog_argv);
|
|
|
|
|
invoker_send_prio(socket_fd, prog_prio);
|
|
|
|
|
invoker_send_delay(socket_fd, respawn_delay);
|
|
|
|
|
invoker_send_ids(socket_fd, getuid(), getgid());
|
|
|
|
|
if (( magic_options & INVOKER_MSG_MAGIC_OPTION_SPLASH_SCREEN ) != 0)
|
|
|
|
|
invoker_send_splash_file(socket_fd, splash_file);
|
|
|
|
|
if (( magic_options & INVOKER_MSG_MAGIC_OPTION_LANDSCAPE_SPLASH_SCREEN ) != 0)
|
|
|
|
|
invoker_send_landscape_splash_file(socket_fd, landscape_splash_file);
|
|
|
|
|
invoker_send_io(socket_fd);
|
|
|
|
|
invoker_send_env(socket_fd);
|
|
|
|
|
invoker_send_end(socket_fd);
|
|
|
|
|
|
|
|
|
|
if (prog_name)
|
|
|
|
|
{
|
|
|
|
|
free(prog_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int exit_status = wait_for_launched_process_to_exit(socket_fd, wait_term);
|
|
|
|
|
return exit_status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Invokes the given application
|
|
|
|
|
static int invoke(int prog_argc, char **prog_argv, char *prog_name,
|
|
|
|
|
enum APP_TYPE app_type, uint32_t magic_options, bool wait_term, unsigned int respawn_delay,
|
|
|
|
|
@ -818,7 +806,7 @@ int main(int argc, char *argv[])
|
|
|
|
|
usage(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pipe(g_sigPipe) == -1)
|
|
|
|
|
if (pipe(g_signal_pipe) == -1)
|
|
|
|
|
{
|
|
|
|
|
report(report_error, "Creating a pipe for Unix signals failed!\n");
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|