Index: ossp-pkg/l2/l2_ch_pipe.c RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_ch_pipe.c,v rcsdiff -q -kk '-r1.23' '-r1.24' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ch_pipe.c,v' 2>/dev/null --- l2_ch_pipe.c 2001/10/02 15:51:32 1.23 +++ l2_ch_pipe.c 2001/10/04 12:34:41 1.24 @@ -62,7 +62,7 @@ if (sig == SIGCHLD) { TRACE("SIGCHLD caught"); - Pid = waitpid(-1, &iStatus, WUNTRACED); + Pid = waitpid(-1, &iStatus, WUNTRACED | WNOHANG); if (WIFEXITED(iStatus)) TRACE("EXITED child"); /* child finished and returned */ else if (WIFSIGNALED(iStatus)) @@ -314,28 +314,27 @@ if (sigaction(SIGPIPE, &locact, &cfg->sigpipe) < 0) return L2_ERR_SYS; - if (pipe(cfg->piFd) == -1) /* open the pipe */ + if (pipe(cfg->piFd) == -1) /* open the pipe */ return L2_ERR_SYS; /* short circuit hack, if in oneshot mode and not yet opened then return */ if ((cfg->iRtme == L2_PIPE_RUNTIME_ONESHOT) && (ch->state != L2_CHSTATE_OPENED)) return L2_OK; else - spawn_command(cfg); /* spawn the command process */ - - return L2_OK; + return spawn_command(cfg); /* spawn the command process */ } /* write to channel, possibly recursively */ static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch, l2_level_t level, const char *buf, size_t buf_size) { - l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; - l2_result_t rv; + l2_result_t rv = L2_OK; + l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; - /* we must still spawn the child command process if we are in oneshot mode */ - if ((cfg->iRtme == L2_PIPE_RUNTIME_ONESHOT) && (cfg->Pid != -1)) - spawn_command(cfg); + /* spawn the child command process if we are in oneshot mode */ + if ((cfg->iRtme == L2_PIPE_RUNTIME_ONESHOT) && (cfg->Pid == -1)) + if (spawn_command(cfg) != L2_OK) + return L2_ERR_SYS; /* immediate return if we can't spawn command */ /* write message to channel pipe */ if (write(cfg->piFd[1], buf, buf_size) == -1) { @@ -346,29 +345,26 @@ return rv; return hook_write(ctx, ch, level, buf, buf_size); } - else { /* not broken pipe problem or over the fail limit */ - cfg->iWritefail = 0; /* reset pipe failure counter */ - return L2_ERR_SYS; + else { /* not broken pipe problem or over the fail limit, so panic */ + cfg->iWritefail = 0; /* reset pipe failure counter */ + rv = L2_ERR_SYS; } } - else { /* write() to pipe succeeded */ + else /* write() to pipe succeeded */ cfg->iWritefail = 0; /* reset pipe failure counter */ - return L2_OK; - } + + /* block until child terminates if in oneshot execmode */ + if ((cfg->iRtme == L2_PIPE_RUNTIME_ONESHOT) && (cfg->Pid != -1)) + cfg->Pid = waitpid(cfg->Pid, NULL, WUNTRACED | WNOHANG); + + return rv; } /* close channel */ static l2_result_t hook_close(l2_context_t *ctx, l2_channel_t *ch) { - l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; - - /* restore previous signal context, but only if it was saved and replaced */ - if (&cfg->sigchld.sa_handler) { - if (sigaction(SIGCHLD, &cfg->sigchld, 0) < 0) - return L2_ERR_SYS; - if (sigaction(SIGPIPE, &cfg->sigpipe, 0) < 0) - return L2_ERR_SYS; - } + l2_result_t rv = L2_OK; + l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; /* close null device */ if (cfg->iNulldev != -1) { @@ -382,14 +378,22 @@ cfg->piFd[1] = -1; } - /* kill child process if already started */ + /* restore previous signal context, but only if it was saved and replaced */ + if (&cfg->sigchld.sa_handler) { + if (sigaction(SIGCHLD, &cfg->sigchld, 0) < 0) + rv = L2_ERR_SYS; + if (sigaction(SIGPIPE, &cfg->sigpipe, 0) < 0) + rv = L2_ERR_SYS; + } + + /* kill child process if still running */ if (cfg->Pid != -1) { - if ((kill (cfg->Pid, SIGTERM)) && (errno != ESRCH)) - return L2_ERR_SYS; + kill(cfg->Pid, SIGTERM); + cfg->Pid = waitpid(cfg->Pid, NULL, WUNTRACED | WNOHANG); cfg->Pid = -1; } - return L2_OK; + return rv; } /* destroy channel */