X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=gui.c;h=b0eae64ae129999083263846d60a9bfd939aae2e;hp=a2d4b5f6c7611914b566128f509bea80caf6fe76;hb=5e8d8a8eea6de9459ebdf4498f9f061c84bfa63a;hpb=be46d3b63c855fe63ecc6feb7c4a2d3edab92307 diff --git a/gui.c b/gui.c index a2d4b5f6..b0eae64a 100644 --- a/gui.c +++ b/gui.c @@ -146,7 +146,7 @@ struct exec_task { unsigned flags[2]; /* passed to for_each_line() */ }; -static int find_cmd_byname(char *name) +static int find_cmd_byname(const char *name) { int i; @@ -498,9 +498,18 @@ static __printf_2_3 void curses_log(int ll, const char *fmt,...) /** The log function of para_gui, always set to curses_log(). */ __printf_2_3 void (*para_log)(int, const char*, ...) = curses_log; +/* Call endwin() to reset the terminal into non-visual mode. */ static void shutdown_curses(void) { - def_prog_mode(); + /* + * If para_gui received a terminating signal in external mode, the + * terminal can be in an unusable state at this point because the child + * process might not have caught the signal. In this case endwin() has + * already been called and must not be called again. So we first return + * to program mode, then call endwin(). + */ + if (!curses_active()) + reset_prog_mode(); endwin(); } @@ -509,6 +518,14 @@ __noreturn __printf_2_3 static void die(int exit_code, const char* fmt, ...) { va_list argp; + /* Kill every process in our process group. */ + para_sigaction(SIGTERM, SIG_IGN); + kill(0, SIGTERM); + /* Wait up to two seconds for child processes to die. */ + alarm(2); + while (waitpid(0, NULL, 0) >= 0) + ; /* nothing */ + alarm(0); /* mousemask() exists only in ncurses */ #ifdef NCURSES_MOUSE_VERSION mousemask(~(mmask_t)0, NULL); /* Avoid bad terminal state with xterm. */ @@ -517,9 +534,6 @@ __noreturn __printf_2_3 static void die(int exit_code, const char* fmt, ...) va_start(argp, fmt); vfprintf(stderr, fmt, argp); va_end(argp); - /* kill every process in the process group and exit */ - para_sigaction(SIGTERM, SIG_IGN); - kill(0, SIGTERM); exit(exit_code); } @@ -921,12 +935,7 @@ static int signal_post_select(struct sched *s, __a_unused void *context) switch (ret) { case SIGTERM: die(EXIT_FAILURE, "only the good die young (caught SIGTERM)\n"); - return 1; case SIGINT: - PARA_WARNING_LOG("caught SIGINT, reset\n"); - /* Nothing to do. SIGINT killed our child which gets noticed - * by do_select and resets everything. - */ return 1; case SIGUSR1: PARA_NOTICE_LOG("got SIGUSR1, rereading configuration\n"); @@ -1482,9 +1491,9 @@ static int setup_tasks_and_schedule(void) * The exec task is responsible for printing the output of the currently * running executable to the bottom window. * - * The signal task performs suitable actions according to any signals received. - * For example it refreshes all windows on terminal size changes and resets the - * terminal on \p SIGTERM. + * The signal task performs various actions according to signals received. For + * example, it reloads the configuration file on SIGUSR1, and it shuts down the + * curses system on SIGTERM to restore the terminal settings before exit. * * The input task reads single key strokes from stdin. For each key pressed, it * executes the command handler associated with this key.