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

Reply via email to