#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
+#include <sys/wait.h>
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)
{
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)
{
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 (;;)
{
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();
(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
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)
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;
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);
}