s4:libcli/resolve: don't ignore SIGCHLD anymore
authorStefan Metzmacher <metze@samba.org>
Mon, 6 Oct 2008 07:18:50 +0000 (09:18 +0200)
committerStefan Metzmacher <metze@samba.org>
Sun, 16 Nov 2008 15:22:08 +0000 (16:22 +0100)
This broke ldbedit against a LDAP server,
as the editor is called by "system()" which relies
on getting something useful out of waitpid().

TODO: we should create a generic infrastructure to
      handle temporary forks and integrate the signal
      handling with signal events there.

metze

source4/libcli/resolve/host.c

index 1a695432eecbd2b3b13932bec3f69d2a700b8bde..7d779b06783bd2a6dd42f278f4bb61c39a9a19fb 100644 (file)
@@ -53,10 +53,15 @@ struct host_state {
 */
 static int host_destructor(struct host_state *state)
 {
+       int status;
+
+       kill(state->child, SIGTERM);
        close(state->child_fd);
-       if (state->child != (pid_t)-1) {
-               kill(state->child, SIGTERM);
+       if (waitpid(state->child, &status, WNOHANG) == 0) {
+               kill(state->child, SIGKILL);
+               waitpid(state->child, &status, 0);
        }
+
        return 0;
 }
 
@@ -90,16 +95,23 @@ static void pipe_handler(struct event_context *ev, struct fd_event *fde,
        struct host_state *state = talloc_get_type(c->private_data, struct host_state);
        char address[128];
        int ret;
+       pid_t child = state->child;
+       int status;
 
        /* if we get any event from the child then we know that we
           won't need to kill it off */
-       state->child = (pid_t)-1;
+       talloc_set_destructor(state, NULL);
 
        /* yes, we don't care about EAGAIN or other niceities
           here. They just can't happen with this parent/child
           relationship, and even if they did then giving an error is
           the right thing to do */
        ret = read(state->child_fd, address, sizeof(address)-1);
+       close(state->child_fd);
+       if (waitpid(state->child, &status, WNOHANG) == 0) {
+               kill(state->child, SIGKILL);
+               waitpid(state->child, &status, 0);
+       }
        if (ret <= 0) {
                composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
                return;
@@ -164,10 +176,6 @@ struct composite_context *resolve_name_host_send(TALLOC_CTX *mem_ctx,
                return c;
        }
 
-       /* signal handling in posix really sucks - doing this in a library
-          affects the whole app, but what else to do?? */
-       signal(SIGCHLD, SIG_IGN);
-
        state->child = fork();
        if (state->child == (pid_t)-1) {
                composite_error(c, map_nt_error_from_unix(errno));