summaryrefslogtreecommitdiff
path: root/source4/libcli/resolve/host.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2008-10-06 09:18:50 +0200
committerStefan Metzmacher <metze@samba.org>2008-11-16 16:22:08 +0100
commit8c2c62c5eaf7c6adc445950f4917208dc4bced87 (patch)
treed5f953e5508396b9b857b700724236c19aa1ffb5 /source4/libcli/resolve/host.c
parent45cf68ce8f9426757c37a8352f9d9104be814407 (diff)
downloadsamba-8c2c62c5eaf7c6adc445950f4917208dc4bced87.tar.gz
samba-8c2c62c5eaf7c6adc445950f4917208dc4bced87.tar.bz2
samba-8c2c62c5eaf7c6adc445950f4917208dc4bced87.zip
s4:libcli/resolve: don't ignore SIGCHLD anymore
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
Diffstat (limited to 'source4/libcli/resolve/host.c')
-rw-r--r--source4/libcli/resolve/host.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/source4/libcli/resolve/host.c b/source4/libcli/resolve/host.c
index 1a695432ee..7d779b0678 100644
--- a/source4/libcli/resolve/host.c
+++ b/source4/libcli/resolve/host.c
@@ -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));