The last change in tmux.c to ignore SIGCHLD in main() introduces a bug: the signal handler is never reset back to SIG_DFL and this signal configuration in inherited by the server when it's created, and in turn by the commands that are spawned because signal_del() resets it to the previous value in server_signal_clear(). This causes some problems, as seen in http://bugs.debian.org/579353.
After discussing this with Nicholas on IRC, he suggested merging SIGCHLD handling in main_set_signals(), resetting in clear_signals(), and moving things around to set up the signal handler before creating the server. This required moving libevent initialization earlier (before forking, requiring reinit), but has the benefit of removing some duplicated code. Cumulative patch: Index: server.c =================================================================== RCS file: /cvsroot/tmux/tmux/server.c,v retrieving revision 1.239 diff -u -p -r1.239 server.c --- server.c 8 Apr 2010 07:54:43 -0000 1.239 +++ server.c 27 Apr 2010 17:44:06 -0000 @@ -136,6 +136,12 @@ server_start(char *path) } close(pair[0]); + /* event_init() was called in our parent, we need to reinit. */ + if (event_reinit(ev_base) != 0) + fatal("event_reinit failed"); + + main_clear_signals(); + /* * Must daemonise before loading configuration as the PID changes so * $TMUX would be wrong for sessions created in the config file. @@ -166,22 +172,6 @@ server_start(char *path) setproctitle("server (%s)", rpathbuf); #endif -#ifdef HAVE_BROKEN_KQUEUE - if (setenv("EVENT_NOKQUEUE", "1", 1) != 0) - fatal("setenv failed"); -#endif -#ifdef HAVE_BROKEN_POLL - if (setenv("EVENT_NOPOLL", "1", 1) != 0) - fatal("setenv failed"); -#endif - event_init(); -#ifdef HAVE_BROKEN_KQUEUE - unsetenv("EVENT_NOKQUEUE"); -#endif -#ifdef HAVE_BROKEN_POLL - unsetenv("EVENT_NOPOLL"); -#endif - server_fd = server_create_socket(); server_client_create(pair[1]); Index: tmux.c =================================================================== RCS file: /cvsroot/tmux/tmux/tmux.c,v retrieving revision 1.205 diff -u -p -r1.205 tmux.c --- tmux.c 22 Apr 2010 21:48:49 -0000 1.205 +++ tmux.c 27 Apr 2010 17:44:06 -0000 @@ -40,6 +40,8 @@ struct options global_s_options; /* ses struct options global_w_options; /* window options */ struct environ global_environ; +struct event_base *ev_base; + int debug_level; time_t start_time; char *socket_path; @@ -241,7 +243,6 @@ main(int argc, char **argv) struct keylist *keylist; struct env_data envdata; struct msg_command_data cmddata; - struct sigaction sigact; char *s, *shellcmd, *path, *label, *home, *cause; char cwd[MAXPATHLEN], **var; void *buf; @@ -541,18 +542,6 @@ main(int argc, char **argv) exit(1); } - /* Catch SIGCHLD to avoid a zombie when starting the server. */ - memset(&sigact, 0, sizeof sigact); - sigemptyset(&sigact.sa_mask); - sigact.sa_handler = SIG_IGN; - if (sigaction(SIGCHLD, &sigact, NULL) != 0) - fatal("sigaction failed"); - - /* Initialise the client socket/start the server. */ - if ((main_ibuf = client_init(path, cmdflags, flags)) == NULL) - exit(1); - xfree(path); - #ifdef HAVE_BROKEN_KQUEUE if (setenv("EVENT_NOKQUEUE", "1", 1) != 0) fatal("setenv failed"); @@ -561,7 +550,7 @@ main(int argc, char **argv) if (setenv("EVENT_NOPOLL", "1", 1) != 0) fatal("setenv failed"); #endif - event_init(); + ev_base = event_init(); #ifdef HAVE_BROKEN_KQUEUE unsetenv("EVENT_NOKQUEUE"); #endif @@ -569,10 +558,15 @@ main(int argc, char **argv) unsetenv("EVENT_NOPOLL"); #endif - imsg_compose(main_ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len); - main_set_signals(); + /* Initialise the client socket/start the server. */ + if ((main_ibuf = client_init(path, cmdflags, flags)) == NULL) + exit(1); + xfree(path); + + imsg_compose(main_ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len); + events = EV_READ; if (main_ibuf->w.queued > 0) events |= EV_WRITE; @@ -605,6 +599,8 @@ main_set_signals(void) fatal("sigaction failed"); if (sigaction(SIGTSTP, &sigact, NULL) != 0) fatal("sigaction failed"); + if (sigaction(SIGCHLD, &sigact, NULL) != 0) + fatal("sigaction failed"); signal_set(&main_ev_sigterm, SIGTERM, main_signal, NULL); signal_add(&main_ev_sigterm, NULL); @@ -629,6 +625,8 @@ main_clear_signals(void) fatal("sigaction failed"); if (sigaction(SIGTSTP, &sigact, NULL) != 0) fatal("sigaction failed"); + if (sigaction(SIGCHLD, &sigact, NULL) != 0) + fatal("sigaction failed"); event_del(&main_ev_sigterm); } Index: tmux.h =================================================================== RCS file: /cvsroot/tmux/tmux/tmux.h,v retrieving revision 1.555 diff -u -p -r1.555 tmux.h --- tmux.h 6 Apr 2010 21:59:19 -0000 1.555 +++ tmux.h 27 Apr 2010 17:44:06 -0000 @@ -1252,6 +1252,7 @@ extern struct options global_options; extern struct options global_s_options; extern struct options global_w_options; extern struct environ global_environ; +extern struct event_base *ev_base; extern char *cfg_file; extern int debug_level; extern int be_quiet; @@ -1262,6 +1263,7 @@ void logfile(const char *); const char *getshell(void); int checkshell(const char *); int areshell(const char *); +void main_clear_signals(void); /* cfg.c */ extern int cfg_finished; ------------------------------------------------------------------------------ _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users