s3:winbindd: fix problems with SIGCHLD handling (bug #7317)
authorStefan Metzmacher <metze@samba.org>
Thu, 1 Apr 2010 14:23:06 +0000 (16:23 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 1 Apr 2010 15:25:11 +0000 (17:25 +0200)
The main problem is that we call CatchChild() within the
parent winbindd, which overwrites the signal handler
that was registered by winbindd_setup_sig_chld_handler().

That means winbindd_sig_chld_handler() and winbind_child_died()
are never triggered when a winbindd domain child dies.
As a result will get "broken pipe" for all requests to that domain.

To reduce the risk of similar bugs in future we call
CatchChild() in winbindd_reinit_after_fork() now.

We also use a full winbindd_reinit_after_fork() in the
cache validation child now instead instead of just resetting
the SIGCHLD handler by hand. This will also fix possible
tdb problems on systems without pread/pwrite and disabled mmap
as we now correctly reopen the tdb handle for the child.

metze

source3/winbindd/winbindd.c
source3/winbindd/winbindd_cm.c
source3/winbindd/winbindd_dual.c

index 13cadffab8eec02f05b581422a259e97d7c50c18..d1d33d39f80221e0040c86d07ab765e971a837f0 100644 (file)
@@ -407,7 +407,6 @@ static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
         * so we don't block the main winbindd and the validation
         * code can safely use fork/waitpid...
         */
-       CatchChild();
        child_pid = sys_fork();
 
        if (child_pid == -1) {
@@ -425,16 +424,9 @@ static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
 
        /* child */
 
-       /* install default SIGCHLD handler: validation code uses fork/waitpid */
-       ZERO_STRUCT(act);
-       act.sa_handler = SIG_DFL;
-#ifdef SA_RESTART
-       /* We *want* SIGALRM to interrupt a system call. */
-       act.sa_flags = SA_RESTART;
-#endif
-       sigemptyset(&act.sa_mask);
-       sigaddset(&act.sa_mask,SIGCHLD);
-       sigaction(SIGCHLD,&act,&oldact);
+       if (!winbindd_reinit_after_fork(NULL)) {
+               _exit(0);
+       }
 
        ret = (uint8)winbindd_validate_cache_nobackup();
        DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
index c2df24456886bc84bb0c8b5649c425c16a69c603..c013fae78792dc08ab9a5d9e0ac81988b3b7f58d 100644 (file)
@@ -180,9 +180,6 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain)
        pid_t parent_pid = sys_getpid();
        char *lfile = NULL;
 
-       /* Stop zombies */
-       CatchChild();
-
        if (domain->dc_probe_pid != (pid_t)-1) {
                /*
                 * We might already have a DC probe
index ca6af1f37b5765fcf260f494651e84092f911ab0..eb9ace23d678936dc3b93706454912bb3ef1172b 100644 (file)
@@ -1215,6 +1215,9 @@ bool winbindd_reinit_after_fork(const char *logfilename)
                                            logfilename))
                return false;
 
+       /* Stop zombies in children */
+       CatchChild();
+
        /* Don't handle the same messages as our parent. */
        messaging_deregister(winbind_messaging_context(),
                             MSG_SMB_CONF_UPDATED, NULL);
@@ -1338,9 +1341,6 @@ static bool fork_domain_child(struct winbindd_child *child)
 
        DEBUG(10, ("Child process %d\n", (int)sys_getpid()));
 
-       /* Stop zombies in children */
-       CatchChild();
-
        state.sock = fdpair[0];
        close(fdpair[1]);