mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
runcmd: use a pipe for stdin to child processes
this allows child processes to detect the exit of the parent by looking for EOF on stdin
This commit is contained in:
parent
711c18c230
commit
81c564798c
@ -33,9 +33,10 @@
|
||||
struct samba_runcmd_state {
|
||||
int stdout_log_level;
|
||||
int stderr_log_level;
|
||||
struct tevent_fd *fde_stdin;
|
||||
struct tevent_fd *fde_stdout;
|
||||
struct tevent_fd *fde_stderr;
|
||||
int fd_stdout, fd_stderr;
|
||||
int fd_stdin, fd_stdout, fd_stderr;
|
||||
char *arg0;
|
||||
pid_t pid;
|
||||
char buf[1024];
|
||||
@ -72,7 +73,7 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
struct tevent_req *req;
|
||||
struct samba_runcmd_state *state;
|
||||
int p1[2], p2[2];
|
||||
int p1[2], p2[2], p3[2];
|
||||
char **argv;
|
||||
va_list ap;
|
||||
|
||||
@ -100,9 +101,7 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
|
||||
tevent_req_error(req, errno);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
state->pid = fork();
|
||||
if (state->pid == (pid_t)-1) {
|
||||
if (pipe(p3) != 0) {
|
||||
close(p1[0]);
|
||||
close(p1[1]);
|
||||
close(p2[0]);
|
||||
@ -111,14 +110,30 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
state->pid = fork();
|
||||
if (state->pid == (pid_t)-1) {
|
||||
close(p1[0]);
|
||||
close(p1[1]);
|
||||
close(p2[0]);
|
||||
close(p2[1]);
|
||||
close(p3[0]);
|
||||
close(p3[1]);
|
||||
tevent_req_error(req, errno);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
if (state->pid != 0) {
|
||||
/* the parent */
|
||||
close(p1[1]);
|
||||
close(p2[1]);
|
||||
close(p3[0]);
|
||||
state->fd_stdout = p1[0];
|
||||
state->fd_stderr = p2[0];
|
||||
state->fd_stdin = p3[1];
|
||||
|
||||
set_blocking(state->fd_stdout, false);
|
||||
set_blocking(state->fd_stderr, false);
|
||||
set_blocking(state->fd_stdin, false);
|
||||
|
||||
talloc_set_destructor(state, samba_runcmd_state_destructor);
|
||||
|
||||
@ -128,8 +143,9 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
|
||||
samba_runcmd_io_handler,
|
||||
req);
|
||||
if (tevent_req_nomem(state->fde_stdout, req)) {
|
||||
close(p1[0]);
|
||||
close(p2[0]);
|
||||
close(state->fd_stdout);
|
||||
close(state->fd_stderr);
|
||||
close(state->fd_stdin);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_fd_set_auto_close(state->fde_stdout);
|
||||
@ -140,11 +156,23 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
|
||||
samba_runcmd_io_handler,
|
||||
req);
|
||||
if (tevent_req_nomem(state->fde_stdout, req)) {
|
||||
close(p2[0]);
|
||||
close(state->fd_stderr);
|
||||
close(state->fd_stdin);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_fd_set_auto_close(state->fde_stderr);
|
||||
|
||||
state->fde_stdin = tevent_add_fd(ev, state,
|
||||
state->fd_stdin,
|
||||
0,
|
||||
samba_runcmd_io_handler,
|
||||
req);
|
||||
if (tevent_req_nomem(state->fde_stdin, req)) {
|
||||
close(state->fd_stdin);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_fd_set_auto_close(state->fde_stdin);
|
||||
|
||||
if (!timeval_is_zero(&endtime)) {
|
||||
tevent_req_set_endtime(req, ev, endtime);
|
||||
}
|
||||
@ -155,6 +183,7 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
|
||||
/* the child */
|
||||
close(p1[0]);
|
||||
close(p2[0]);
|
||||
close(p3[1]);
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
@ -164,7 +193,7 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
|
||||
tevent_re_initialise(ev);
|
||||
|
||||
/* setup for logging to go to the parents debug log */
|
||||
open("/dev/null", O_RDONLY); /* for stdin */
|
||||
dup2(p3[0], 0);
|
||||
dup2(p1[1], 1);
|
||||
dup2(p2[1], 2);
|
||||
|
||||
@ -211,9 +240,19 @@ static void samba_runcmd_io_handler(struct tevent_context *ev,
|
||||
if (fde == state->fde_stdout) {
|
||||
level = state->stdout_log_level;
|
||||
fd = state->fd_stdout;
|
||||
} else {
|
||||
} else if (fde == state->fde_stderr) {
|
||||
level = state->stderr_log_level;
|
||||
fd = state->fd_stderr;
|
||||
} else if (fde == state->fde_stdin) {
|
||||
char c;
|
||||
if (read(state->fd_stdin, &c, 1) != 1) {
|
||||
/* the child has closed its stdin */
|
||||
talloc_free(fde);
|
||||
state->fde_stdin = NULL;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(flags & TEVENT_FD_READ)) {
|
||||
|
Loading…
Reference in New Issue
Block a user