diff --git a/legacy/elementary/src/bin/quicklaunch.c b/legacy/elementary/src/bin/quicklaunch.c index c8284344e8..7ef131cefb 100644 --- a/legacy/elementary/src/bin/quicklaunch.c +++ b/legacy/elementary/src/bin/quicklaunch.c @@ -10,11 +10,68 @@ #include #include #include +#include static double restart_time = 0.0; #define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path)) +static struct sigaction old_sigint; +static struct sigaction old_sigterm; +static struct sigaction old_sigquit; +static struct sigaction old_sigalrm; +static struct sigaction old_sigusr1; +static struct sigaction old_sigusr2; +static struct sigaction old_sighup; +static struct sigaction old_sigchld; +static struct sigaction old_sigsegv; +static struct sigaction old_sigill; +static struct sigaction old_sigfpe; +static struct sigaction old_sigbus; +static struct sigaction old_sigabrt; + +static void +post_fork(void *data) +{ + sigaction(SIGINT, &old_sigint, NULL); + sigaction(SIGTERM, &old_sigterm, NULL); + sigaction(SIGQUIT, &old_sigquit, NULL); + sigaction(SIGALRM, &old_sigalrm, NULL); + sigaction(SIGUSR1, &old_sigusr1, NULL); + sigaction(SIGUSR2, &old_sigusr2, NULL); + sigaction(SIGHUP, &old_sighup, NULL); + sigaction(SIGCHLD, &old_sigchld, NULL); + sigaction(SIGSEGV, &old_sigsegv, NULL); + sigaction(SIGILL, &old_sigill, NULL); + sigaction(SIGFPE, &old_sigfpe, NULL); + sigaction(SIGBUS, &old_sigbus, NULL); + sigaction(SIGABRT, &old_sigabrt, NULL); +} + +static void +child_handler(int x, siginfo_t *info, void *data) +{ + int status; + pid_t pid; + + while ((pid = waitpid(-1, &status, WNOHANG)) > 0); +} + +static void +crash_handler(int x, siginfo_t *info, void *data) +{ + double t; + + EINA_ERROR_PERR("elementary_quicklaunch: crash detected. restarting.\n"); + t = ecore_time_get(); + if ((t - restart_time) <= 2.0) + { + EINA_ERROR_PERR("elementary_quicklaunch: crash too fast - less than 2 seconds. abort restart\n"); + exit(-1); + } + ecore_app_restart(); +} + static void handle_run(int fd, unsigned long bytes) { @@ -36,32 +93,10 @@ handle_run(int fd, unsigned long bytes) for (i = 0; i < argc; i++) argv[i] = buf + (unsigned long)argv[i]; cwd = argv[argc - 1] + strlen(argv[argc - 1]) + 1; elm_quicklaunch_prepare(argc, argv); - elm_quicklaunch_fork(argc, argv, cwd); + elm_quicklaunch_fork(argc, argv, cwd, post_fork, NULL); elm_quicklaunch_cleanup(); } -static void -child_handler(int n) -{ - int status; - wait(&status); -} - -EAPI void -crash_handler(int x, siginfo_t *info, void *data) -{ - double t; - - EINA_ERROR_PERR("elementary_quicklaunch: crash detected. restarting.\n"); - t = ecore_time_get(); - if ((t - restart_time) <= 2.0) - { - EINA_ERROR_PERR("elementary_quicklaunch: crash too fast - less than 2 seconds. abort restart\n"); - exit(-1); - } - ecore_app_restart(); -} - int main(int argc, char **argv) { @@ -117,41 +152,98 @@ main(int argc, char **argv) exit(-1); } elm_quicklaunch_init(argc, argv); - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGALRM, SIG_DFL); - signal(SIGUSR1, SIG_DFL); - signal(SIGUSR2, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGCHLD, child_handler); - restart_time = ecore_time_get(); + + action.sa_handler = SIG_DFL; + action.sa_restorer = NULL; + action.sa_sigaction = NULL; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGINT, &action, &old_sigint); + action.sa_handler = SIG_DFL; + action.sa_restorer = NULL; + action.sa_sigaction = NULL; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGTERM, &action, &old_sigterm); + + action.sa_handler = SIG_DFL; + action.sa_restorer = NULL; + action.sa_sigaction = NULL; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGQUIT, &action, &old_sigquit); + + action.sa_handler = SIG_DFL; + action.sa_restorer = NULL; + action.sa_sigaction = NULL; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGALRM, &action, &old_sigalrm); + + action.sa_handler = SIG_DFL; + action.sa_restorer = NULL; + action.sa_sigaction = NULL; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGUSR1, &action, &old_sigusr1); + + action.sa_handler = SIG_DFL; + action.sa_restorer = NULL; + action.sa_sigaction = NULL; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGUSR2, &action, &old_sigusr2); + + action.sa_handler = SIG_DFL; + action.sa_restorer = NULL; + action.sa_sigaction = NULL; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGHUP, &action, &old_sighup); + + action.sa_handler = NULL; + action.sa_restorer = NULL; + action.sa_sigaction = child_handler; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGCHLD, &action, &old_sigchld); + + action.sa_handler = NULL; + action.sa_restorer = NULL; action.sa_sigaction = crash_handler; action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; sigemptyset(&action.sa_mask); - sigaction(SIGSEGV, &action, NULL); + sigaction(SIGSEGV, &action, &old_sigsegv); + action.sa_handler = NULL; + action.sa_restorer = NULL; action.sa_sigaction = crash_handler; action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; sigemptyset(&action.sa_mask); - sigaction(SIGILL, &action, NULL); + sigaction(SIGILL, &action, &old_sigill); + action.sa_handler = NULL; + action.sa_restorer = NULL; action.sa_sigaction = crash_handler; action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; sigemptyset(&action.sa_mask); - sigaction(SIGFPE, &action, NULL); + sigaction(SIGFPE, &action, &old_sigfpe); + action.sa_handler = NULL; + action.sa_restorer = NULL; action.sa_sigaction = crash_handler; action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; sigemptyset(&action.sa_mask); - sigaction(SIGBUS, &action, NULL); + sigaction(SIGBUS, &action, &old_sigbus); + action.sa_handler = NULL; + action.sa_restorer = NULL; action.sa_sigaction = crash_handler; action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; sigemptyset(&action.sa_mask); - sigaction(SIGABRT, &action, NULL); + sigaction(SIGABRT, &action, &old_sigabrt); for (;;) { @@ -169,6 +261,7 @@ main(int argc, char **argv) char line[4096]; read(fd, &bytes, sizeof(unsigned long)); + ecore_app_args_set(argc, (const char **)argv); handle_run(fd, bytes); } elm_quicklaunch_sub_shutdown(); diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index 03e19db8c6..a8809d9be0 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -155,7 +155,7 @@ extern "C" { EAPI void elm_quicklaunch_shutdown(void); EAPI void elm_quicklaunch_seed(void); EAPI Evas_Bool elm_quicklaunch_prepare(int argc, char **argv); - EAPI Evas_Bool elm_quicklaunch_fork(int argc, char **argv, char *cwd); + EAPI Evas_Bool elm_quicklaunch_fork(int argc, char **argv, char *cwd, void (postfork_func) (void *data), void *postfork_data); EAPI void elm_quicklaunch_cleanup(void); EAPI int elm_quicklaunch_fallback(int argc, char **argv); EAPI char *elm_quicklaunch_exe_path_get(const char *exe); diff --git a/legacy/elementary/src/lib/elm_main.c b/legacy/elementary/src/lib/elm_main.c index 6ada9b77ba..67b6cf3f41 100644 --- a/legacy/elementary/src/lib/elm_main.c +++ b/legacy/elementary/src/lib/elm_main.c @@ -278,28 +278,6 @@ elm_quicklaunch_init(int argc, char **argv) (double)_elm_config->finger_size * _elm_config->scale; if (elm_finger_size) _elm_config->finger_size = atoi(elm_finger_size); - - /* FIXME: implement quickstart below */ - /* if !quickstart return - * else - * set up fast-start-fifo (in $ELM_FAST_START_FIFO) - * sit on blocking read - * read 2 bytes == length of data in bytes including nulls - * read N bytes (must be < (page_size - 2)) - * format: exename\0exepath\0[arg1\0][arg2\0][...] - * dlopen exepath - * dlsym elm_main in exe - * if (elm_main ! exists) - * ecore_exe exename - * else - * fork() - * [child] - * call exit(elm_main()); - * [parent] - * close x fd the nasty way (with close()) - * ecore_x_shutdown() - * ecore_x_init() etc. etc. loop back to blocking on fifo read - */ } EAPI void @@ -326,7 +304,6 @@ elm_quicklaunch_sub_init(int argc, char **argv) ECORE_X_EVENT_MASK_WINDOW_PROPERTY); _elm_event_property_change = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, _elm_window_property_change, NULL); - /* FIXME if quickstart this happens in child */ if (ecore_x_window_prop_card32_get(ecore_x_window_root_first_get(), _elm_atom_enlightenment_scale, &val, 1) > 0) @@ -465,8 +442,30 @@ elm_quicklaunch_prepare(int argc, char **argv) return 1; } +static void +save_env(void) +{ + int i, size; + extern char **environ; + char **oldenv, **p; + + oldenv = environ; + + for (i = 0, size = 0; environ[i] != NULL; i++) + size += strlen(environ[i]) + 1; + + p = malloc((i + 1) * sizeof(char *)); + if (!p) return; + + environ = p; + + for (i = 0; oldenv[i] != NULL; i++) + environ[i] = strdup(oldenv[i]); + environ[i] = NULL; +} + EAPI Evas_Bool -elm_quicklaunch_fork(int argc, char **argv, char *cwd) +elm_quicklaunch_fork(int argc, char **argv, char *cwd, void (postfork_func) (void *data), void *postfork_data) { pid_t child; int ret; @@ -503,9 +502,25 @@ elm_quicklaunch_fork(int argc, char **argv, char *cwd) perror("could not fork"); return 0; } + if (postfork_func) postfork_func(postfork_data); + setsid(); if (chdir(cwd) != 0) perror("could not chdir"); + // FIXME: this is very linux specific. it changes argv[0] of the process + // so ps etc. report what you'd expect. for other unixes and os's this + // may just not work + save_env(); + if (real_argv) + { + char *lastarg, *p; + + ecore_app_args_get(&real_argc, &real_argv); + lastarg = real_argv[real_argc - 1] + strlen(real_argv[real_argc - 1]); + for (p = real_argv[0]; p < lastarg; p++) *p = 0; + strcpy(real_argv[0], argv[0]); + } + ecore_app_args_set(argc, (const char **)argv); ret = qr_main(argc, argv); exit(ret); }