lib/tevent: fix race with signals and tevent_common_add_signal
authorRusty Russell <rusty@rustcorp.com.au>
Fri, 28 Aug 2009 02:34:22 +0000 (12:04 +0930)
committerKarolin Seeger <kseeger@samba.org>
Wed, 9 Sep 2009 10:27:17 +0000 (12:27 +0200)
We carefully preserve the old signal handler, but we replace it before
we've set up everything; in particular, if we fail setting up the
pipe_hack we could write a NUL char to stdout (fd 0), instead of
calling the old signal handler.

Replace the signal handler as the very last thing we do.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
(cherry picked from commit 6abb637e3e0d23635fdbbb91c163731b325d696d)

lib/tevent/tevent_signal.c

index 429995318be8787bcbd664b804fa76c03b69037a..2c87463b95de50fb5ed05df1f9344b9bc9612d1c 100644 (file)
@@ -219,6 +219,26 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
                return NULL;
        }
 
+       /* we need to setup the pipe hack handler if not already
+          setup */
+       if (ev->pipe_fde == NULL) {
+               if (sig_state->pipe_hack[0] == 0 &&
+                   sig_state->pipe_hack[1] == 0) {
+                       if (pipe(sig_state->pipe_hack) == -1) {
+                               talloc_free(se);
+                               return NULL;
+                       }
+                       ev_set_blocking(sig_state->pipe_hack[0], false);
+                       ev_set_blocking(sig_state->pipe_hack[1], false);
+               }
+               ev->pipe_fde = tevent_add_fd(ev, ev, sig_state->pipe_hack[0],
+                                            TEVENT_FD_READ, signal_pipe_handler, NULL);
+               if (!ev->pipe_fde) {
+                       talloc_free(se);
+                       return NULL;
+               }
+       }
+
        /* only install a signal handler if not already installed */
        if (sig_state->sig_handlers[signum] == NULL) {
                struct sigaction act;
@@ -255,26 +275,6 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
        talloc_set_destructor(se, tevent_signal_destructor);
        talloc_set_destructor(sl, tevent_common_signal_list_destructor);
 
-       /* we need to setup the pipe hack handler if not already
-          setup */
-       if (ev->pipe_fde == NULL) {
-               if (sig_state->pipe_hack[0] == 0 && 
-                   sig_state->pipe_hack[1] == 0) {
-                       if (pipe(sig_state->pipe_hack) == -1) {
-                               talloc_free(se);
-                               return NULL;
-                       }
-                       ev_set_blocking(sig_state->pipe_hack[0], false);
-                       ev_set_blocking(sig_state->pipe_hack[1], false);
-               }
-               ev->pipe_fde = tevent_add_fd(ev, ev, sig_state->pipe_hack[0],
-                                            TEVENT_FD_READ, signal_pipe_handler, NULL);
-               if (!ev->pipe_fde) {
-                       talloc_free(se);
-                       return NULL;
-               }
-       }
-
        return se;
 }