I wonder if to make it nicer we could unify the signal set functions
into one set_signals(void (*)(int, short, void *)). And similarly could
have one clear_signals function.

All the processes could ignore SIGINT, SIGPIPE, SIGUSR2, SIGTSTP,
SIGHUP, and all catch SIGCONT, SIGTERM, SIGWINCH, SIGCHLD, SIGUSR1, then
the actual handler could just ignore the ones not wanted.


On Tue, Apr 27, 2010 at 08:04:24PM +0200, Romain Francoise wrote:
> 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

------------------------------------------------------------------------------
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to