diff --git a/src/bin/e.h b/src/bin/e.h index e56c788fb..03b7a30b9 100644 --- a/src/bin/e.h +++ b/src/bin/e.h @@ -278,6 +278,7 @@ extern EAPI Eina_Bool evil; extern EAPI Eina_Bool starting; extern EAPI Eina_Bool stopping; extern EAPI Eina_Bool restart; +extern EAPI Eina_Bool e_nopause; extern EAPI Eina_Bool e_precache_end; extern EAPI Eina_Bool x_fatal; diff --git a/src/bin/e_alert.c b/src/bin/e_alert.c index e24c63f99..a38c2526b 100644 --- a/src/bin/e_alert.c +++ b/src/bin/e_alert.c @@ -30,62 +30,12 @@ e_alert_composite_win(Ecore_X_Window root, Ecore_X_Window comp) } EAPI void -e_alert_show(int sig) +e_alert_show(void) { - char *args[4]; - pid_t pid; - -#define E_ALERT_EXE "/enlightenment/utils/enlightenment_alert" - - args[0] = alloca(strlen(e_prefix_lib_get()) + strlen(E_ALERT_EXE) + 1); - strcpy(args[0], e_prefix_lib_get()); - strcat(args[0], E_ALERT_EXE); - - args[1] = alloca(10); - snprintf(args[1], 10, "%d", sig); - - args[2] = alloca(21); - snprintf(args[2], 21, "%lu", (long unsigned int)getpid()); - - args[3] = NULL; - - pid = fork(); - if (pid < -1) - goto restart_e; - - if (pid == 0) + if (!e_nopause) { - /* The child process */ - execvp(args[0], args); + fprintf(stderr, "PAUSE !\n"); + pause(); } - else - { - /* The parent process */ - pid_t ret; - int status = 0; - - do - { - ret = waitpid(pid, &status, 0); - if (errno == ECHILD) - break ; - } - while (ret != pid); - - if (status == 0) - goto restart_e; - - if (!WIFEXITED(status)) - goto restart_e; - - if (WEXITSTATUS(status) == 1) - goto restart_e; - - exit(-11); - } - - restart_e: - if (getenv("E_START_MTRACK")) - e_util_env_set("MTRACK", "track"); - ecore_app_restart(); + return ; } diff --git a/src/bin/e_alert.h b/src/bin/e_alert.h index 68aafea0f..dead6c743 100644 --- a/src/bin/e_alert.h +++ b/src/bin/e_alert.h @@ -13,7 +13,7 @@ typedef enum _E_Alert_Op_Type EINTERN int e_alert_init(void); EINTERN int e_alert_shutdown(void); -EAPI void e_alert_show(int sig); +EAPI void e_alert_show(void); #endif #endif diff --git a/src/bin/e_alert_main.c b/src/bin/e_alert_main.c index 188887894..0bde77eef 100644 --- a/src/bin/e_alert_main.c +++ b/src/bin/e_alert_main.c @@ -51,6 +51,7 @@ static const char *title = NULL, *str1 = NULL, *str2 = NULL; static int ret = 0, sig = 0; static pid_t pid; static Eina_Bool tainted = EINA_TRUE; +static const char *backtrace = NULL; int main(int argc, char **argv) @@ -72,6 +73,8 @@ main(int argc, char **argv) sig = atoi(argv[i]); // signal else if (i == 2) pid = atoi(argv[i]); // E's pid + else if (i == 3) + backtrace = argv[i]; } tmp = getenv("E17_TAINTED"); @@ -519,15 +522,33 @@ _e_alert_draw_text(void) if (!tainted) { - snprintf(msg, sizeof(msg), - "This is not meant to happen and is likely a sign of \n" - "a bug in Enlightenment or the libraries it relies \n" - "on. You can gdb attach to this process (%d) now \n" - "to try debug it or you could exit, or just hit \n" - "restart to try and get your desktop back the way \n" - "it was.\n" - "\n" - "Please compile E17 and EFL with -g in your CFLAGS.\n", pid); + if (backtrace) + { + snprintf(msg, sizeof(msg), + "This is not meant to happen and is likely a sign of \n" + "a bug in Enlightenment or the libraries it relies \n" + "on. You will find an backtrace of E17 (%d) in :\n" + "'%s'\n" + "Before reporting issue, compile latest E17 and EFL\n" + "from svn with '-g -ggdb3' in your CFLAGS.\n" + "You can then report this crash on :\n" + "http://trac.enlightenment.org/e/.\n", + pid, backtrace); + } + else + { + snprintf(msg, sizeof(msg), + "This is not meant to happen and is likely a sign of \n" + "a bug in Enlightenment or the libraries it relies \n" + "on. You can gdb attach to this process (%d) now \n" + "to try debug it or you could exit, or just hit \n" + "restart to try and get your desktop back the way \n" + "it was.\n" + "\n" + "Please compile latest svn E17 and EFL with\n" + "-g and -ggdb3 in your CFLAGS.\n", pid); + + } } else { @@ -536,7 +557,8 @@ _e_alert_draw_text(void) "a sign of a bug, but you are using unsupported\n" "modules; before reporting this issue, please\n" "unload them and try to see if the bug is still\n" - "there.\n"); + "there. Also update to latest svn and be sure to\n" + "compile E17 and EFL with -g and -ggdb3 in your CFLAGS"); } strcpy(warn, ""); diff --git a/src/bin/e_main.c b/src/bin/e_main.c index ff9e784d6..c585ffa58 100644 --- a/src/bin/e_main.c +++ b/src/bin/e_main.c @@ -122,6 +122,7 @@ EAPI Eina_Bool evil = EINA_FALSE; EAPI Eina_Bool starting = EINA_TRUE; EAPI Eina_Bool stopping = EINA_FALSE; EAPI Eina_Bool restart = EINA_FALSE; +EAPI Eina_Bool e_nopause = EINA_FALSE; static void _xdg_data_dirs_augment(void) @@ -1200,6 +1201,8 @@ _e_main_parse_arguments(int argc, char **argv) really_know = EINA_TRUE; else if (!strcmp(argv[i], "-locked")) locked = EINA_TRUE; + else if (!strcmp(argv[i], "-nopause")) + e_nopause = EINA_TRUE; else if ((!strcmp(argv[i], "-h")) || (!strcmp(argv[i], "-help")) || (!strcmp(argv[i], "--help"))) diff --git a/src/bin/e_signals.c b/src/bin/e_signals.c index 59ccd3945..b095b5207 100644 --- a/src/bin/e_signals.c +++ b/src/bin/e_signals.c @@ -54,121 +54,60 @@ _e_write_safe_int(int fd, const char *buf, size_t size) } } -static void -_e_gdb_print_backtrace(int fd __UNUSED__) -{ - // FIXME: we are in a segv'd state. do as few function calls and things - // depending on a known working state as possible. this also prevents the - // white box allowing recovery or deeper gdbing, thus until this works - // properly, it's disabled (properly means always reliable, always - // printf bt and allows e to continue and pop up box, perferably allowing - // debugging in the gui etc. etc. -#if 0 - char cmd[1024]; - size_t size; - int ret; - - if (getenv("E_NO_GDB_BACKTRACE")) - return; - - size = snprintf(cmd, sizeof(cmd), - "gdb --pid=%d " - "-ex 'thread apply all bt' " - "-ex detach -ex quit", getpid()); - - if (size >= sizeof(cmd)) - return; - - _e_write_safe(fd, "EXECUTING GDB AS: "); - _e_write_safe_int(fd, cmd, size); - _e_write_safe(fd, "\n"); - ret = system(cmd); // TODO: use popen() or fork()+pipe()+exec() and save to 'fd' -#endif -} - -#define _e_backtrace(msg) _e_backtrace_int(2, msg, sizeof(msg)) -static void -_e_backtrace_int(int fd, const char *msg, size_t msg_len) -{ - char attachmsg[1024]; - void *array[255]; - size_t size; - - return; // disable. causes hangs and problems - - _e_write_safe_int(fd, msg, msg_len); - _e_write_safe(fd, "\nBEGIN TRACEBACK\n"); - size = backtrace(array, 255); - backtrace_symbols_fd(array, size, fd); - _e_write_safe(fd, "END TRACEBACK\n"); - - size = snprintf(attachmsg, sizeof(attachmsg), - "debug with: gdb --pid=%d\n", getpid()); - if (size < sizeof(attachmsg)) - _e_write_safe_int(fd, attachmsg, size); - - _e_gdb_print_backtrace(fd); -} - /* a tricky little devil, requires e and it's libs to be built * with the -rdynamic flag to GCC for any sort of decent output. */ EAPI void e_sigseg_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__) { - _e_backtrace("**** SEGMENTATION FAULT ****"); _e_x_composite_shutdown(); ecore_x_pointer_ungrab(); ecore_x_keyboard_ungrab(); ecore_x_ungrab(); ecore_x_sync(); - e_alert_show(SIGSEGV); + e_alert_show(); } EAPI void e_sigill_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__) { - _e_backtrace("**** ILLEGAL INSTRUCTION ****"); _e_x_composite_shutdown(); ecore_x_pointer_ungrab(); ecore_x_keyboard_ungrab(); ecore_x_ungrab(); ecore_x_sync(); - e_alert_show(SIGILL); + e_alert_show(); } EAPI void e_sigfpe_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__) { - _e_backtrace("**** FLOATING POINT EXCEPTION ****"); _e_x_composite_shutdown(); ecore_x_pointer_ungrab(); ecore_x_keyboard_ungrab(); ecore_x_ungrab(); ecore_x_sync(); - e_alert_show(SIGFPE); + e_alert_show(); } EAPI void e_sigbus_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__) { - _e_backtrace("**** BUS ERROR ****"); _e_x_composite_shutdown(); ecore_x_pointer_ungrab(); ecore_x_keyboard_ungrab(); ecore_x_ungrab(); ecore_x_sync(); - e_alert_show(SIGBUS); + e_alert_show(); } EAPI void e_sigabrt_act(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__) { - _e_backtrace("**** ABORT ****"); _e_x_composite_shutdown(); ecore_x_pointer_ungrab(); ecore_x_keyboard_ungrab(); ecore_x_ungrab(); ecore_x_sync(); - e_alert_show(SIGABRT); + e_alert_show(); } diff --git a/src/bin/e_start_main.c b/src/bin/e_start_main.c index 09e0c14f1..68900f58d 100644 --- a/src/bin/e_start_main.c +++ b/src/bin/e_start_main.c @@ -8,13 +8,18 @@ #include #include #include +#include #include #include #ifdef HAVE_ALLOCA_H # include #endif +#include + #include +static Eina_Bool tainted = EINA_FALSE; + static void env_set(const char *var, const char *val); EAPI int prefix_determine(char *argv0); @@ -217,12 +222,28 @@ main(int argc, char **argv) int i, valgrind_mode = 0; int valgrind_tool = 0; int valgrind_gdbserver = 0; - char buf[16384], **args, *p; + char buf[16384], **args, *home; char valgrind_path[PATH_MAX] = ""; const char *valgrind_log = NULL; Eina_Bool really_know = EINA_FALSE; + Eina_Bool restart = EINA_TRUE; eina_init(); + + /* reexcute myself with dbus-launch if dbus-launch is not running yet */ + if ((!getenv("DBUS_SESSION_BUS_ADDRESS")) && + (!getenv("DBUS_LAUNCHD_SESSION_BUS_SOCKET"))) + { + char **dbus_argv; + + dbus_argv = alloca(argc + 3 + sizeof (char *)); + dbus_argv[0] = "dbus-launch"; + dbus_argv[1] = "--exit-with-session"; + copy_args(dbus_argv + 2, argv, argc); + dbus_argv[2 + argc] = NULL; + execvp("dbus-launch", dbus_argv); + } + prefix_determine(argv[0]); env_set("E_START", argv[0]); @@ -254,6 +275,11 @@ main(int argc, char **argv) else printf("Unknown valgrind option: %s\n", argv[i]); } + else if (!strcmp(argv[i], "-display")) + { + i++; + env_set("DISPLAY", argv[i]); + } else if (!strcmp(argv[i], "-massif")) valgrind_tool = 1; else if (!strcmp(argv[i], "-callgrind")) @@ -312,15 +338,15 @@ main(int argc, char **argv) putchar('\n'); /* mtrack memory tracker support */ - p = getenv("HOME"); - if (p) + home = getenv("HOME"); + if (home) { FILE *f; /* if you have ~/.e-mtrack, then the tracker will be enabled * using the content of this file as the path to the mtrack.so * shared object that is the mtrack preload */ - snprintf(buf, sizeof(buf), "%s/.e-mtrack", p); + snprintf(buf, sizeof(buf), "%s/.e-mtrack", home); f = fopen(buf, "r"); if (f) { @@ -335,40 +361,143 @@ main(int argc, char **argv) env_set("LD_PRELOAD", buf); env_set("MTRACK", "track"); env_set("E_START_MTRACK", "track"); - snprintf(buf, sizeof(buf), "%s/.e-mtrack.log", p); + snprintf(buf, sizeof(buf), "%s/.e-mtrack.log", home); env_set("MTRACK_TRACE_FILE", buf); } fclose(f); } } - /* try dbus-launch */ + /* run e directly now */ snprintf(buf, sizeof(buf), "%s/enlightenment", eina_prefix_bin_get(pfx)); args = alloca((argc + 2 + VALGRIND_MAX_ARGS) * sizeof(char *)); - if ((!getenv("DBUS_SESSION_BUS_ADDRESS")) && - (!getenv("DBUS_LAUNCHD_SESSION_BUS_SOCKET"))) - { - args[0] = "dbus-launch"; - args[1] = "--exit-with-session"; - - i = 2 + valgrind_append(args + 2, valgrind_gdbserver, valgrind_mode, valgrind_tool, valgrind_path, valgrind_log); - args[i++] = buf; - copy_args(args + i, argv + 1, argc - 1); - args[i + argc - 1] = NULL; - execvp("dbus-launch", args); - } - - /* dbus-launch failed - run e direct */ i = valgrind_append(args, valgrind_gdbserver, valgrind_mode, valgrind_tool, valgrind_path, valgrind_log); args[i++] = buf; copy_args(args + i, argv + 1, argc - 1); args[i + argc - 1] = NULL; - execv(args[0], args); + /* execv(args[0], args); */ + + /* not run at the moment !! */ + + + /* Now looping until */ + while (restart) + { + pid_t child; + + tainted = EINA_FALSE; + child = fork(); + + if (child < 0) /* failed attempt */ + return -1; + else if (child == 0) + { + /* in the child */ + ptrace(PTRACE_TRACEME, 0, NULL, NULL); + + execv(args[0], args); + return 0; /* We failed, 0 mean normal exit from E with no restart or crash so let exit */ + } + else + { + /* in the parent */ + pid_t result; + int status; + Eina_Bool done = EINA_FALSE; + + ptrace(PTRACE_ATTACH, child, NULL, NULL); + + result = waitpid(child, &status, 0); + + if (WIFSTOPPED(status)) + ptrace(PTRACE_CONT, child, NULL, NULL); + + while (!done) + { + result = waitpid(child, &status, 0); + + if (result == child) + { + if (WIFSTOPPED(status)) + { + char buffer[4096]; + char *backtrace = NULL; + siginfo_t sig; + int r; + int back; + + r = ptrace(PTRACE_GETSIGINFO, child, NULL, &sig); + back = r == 0 && + sig.si_signo != SIGTRAP ? sig.si_signo : 0; + + if (r != 0 || + (sig.si_signo != SIGSEGV && + sig.si_signo != SIGILL && + sig.si_signo != SIGFPE && + sig.si_signo != SIGBUS && + sig.si_signo != SIGABRT)) + { + ptrace(PTRACE_CONT, child, NULL, back); + continue ; + } + + /* E17 should be in pause, we can detach */ + ptrace(PTRACE_DETACH, child, NULL, back); + + /* And call gdb if available */ + if (home) + { + /* call e_sys gdb */ + snprintf(buffer, 4096, + "%s/enlightenment/utils/enlightenment_sys gdb %i %s/.xsession-errors", + eina_prefix_lib_get(pfx), + child, + home); + r = system(buffer); + + fprintf(stderr, "called gdb with '%s' = %i\n", + buffer, WEXITSTATUS(r)); + + snprintf(buffer, 4096, + "%s/.xsession-errors", + home); + + backtrace = strdup(buffer); + } + + /* call e_alert */ + snprintf(buffer, 4096, + backtrace ? "%s/enlightenment/utils/enlightenment_alert %i %i %s" : "%s/enlightenment/utils/enlightenment_alert %i %i %s", + eina_prefix_lib_get(pfx), + sig.si_signo, + child, + backtrace); + r = system(buffer); + + /* kill e */ + kill(child, SIGKILL); + + if (WEXITSTATUS(r) != 1) + { + restart = EINA_FALSE; + } + } + else if (!WIFEXITED(status)) + { + done = EINA_TRUE; + } + } + else if (result == - 1) + { + done = EINA_TRUE; + restart = EINA_FALSE; + } + } + } + + } - printf("FAILED TO RUN:\n"); - printf(" %s\n", buf); - perror("execv"); return -1; }