Index: ossp-pkg/l2/TODO RCS File: /v/ossp/cvs/ossp-pkg/l2/TODO,v rcsdiff -q -kk '-r1.23' '-r1.24' -u '/v/ossp/cvs/ossp-pkg/l2/TODO,v' 2>/dev/null --- TODO 2001/09/18 14:38:51 1.23 +++ TODO 2001/09/20 16:26:56 1.24 @@ -26,6 +26,8 @@ MS: - implement pipe channel - review pipe handler for dangling descriptors +- configure only checks existance of command in non-shell mode +- find alternative to exec arguments which is hard coded to 256 ISSUES ------ Index: ossp-pkg/l2/l2.pod RCS File: /v/ossp/cvs/ossp-pkg/l2/l2.pod,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/l2/l2.pod,v' 2>/dev/null --- l2.pod 2001/09/14 19:22:38 1.6 +++ l2.pod 2001/09/20 16:26:56 1.7 @@ -102,6 +102,58 @@ =back +=head2 Pipe Output Channel Handler (l2_handler_pipe) + +The Pipe output channel handler C sends the incoming +message to the standard input of a chosen command, passed to the l2 +library as a parameter when calling l2_configure. + +Any command that operates on the standard input (c language descriptor +stdin) can be used, but attention is advised due to the wide +variety of commands and their particular exit behaviours. + +Attention! Commands that exit on their own and with a success return value will +not be restarted, however those returning with non-zero exit codes will be +restarted. L2 reopens closed pipe channels due to faulted command processes in +this way. Should such a reconnection be required after a command's successful +self-termination, l2_channel_open() may be called again on the same pipe channel +pointer previously used. Stream logging will then write to the pipe channel +handler, which will forward the log messages to the given command as always. To +find out if a pipe channel has closed due to the behaviour of its command +process, the l2_channel_write() operation may be called on it with a non-NULL +message parameter, and 0 as the buffsize parameter. The return result will be +L2_OK if the channel is open. Using the C language, such a check might look +like: + +TODO NOTE FROM MICHAEL: This info will change once the pipe channel handler is +redesigned to allow for proper process termination, signal handling of such +processes, and subsequent channel closing!!!!!!!!!!! + + if (l2_channel_write(pPipechannel, L2_LEVEL_NOTICE, "", 0) != L2_OK) + if (l2_channel_open(pPipechannel) != L2_OK) + exit(1); /* failure */ + +The command passed to the pipe channel handler may also be stopped while still +using a L2 stream log. If a command process is stopped no action is taken +until further logging occurs. As soon as the pipe channel handler receives a +message due to a l2_stream_log operation, it will attempt to restart the +stopped command process and write to its standard input. If the effort to +restart the command process fails then the command process is considered +dead, and L2 will terminate the process and close the channel. A +l2_channel_open() will then reopen the pipe channel using configuration +information previously entered with l2_channel_configure(). + +It provides the following channel parameters: + +=over 4 + +=item B (optional, C) + +L2 will execute the command at this user-provided path, and pipe messages to +its standard input when l2_stream_log operations are called. + +=back + =head2 SMTP Output Channel Handler (l2_handler_smtp) The SMTP output channel handler C sends the incoming 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.12' '-r1.13' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ch_pipe.c,v' 2>/dev/null --- l2_ch_pipe.c 2001/09/19 16:39:44 1.12 +++ l2_ch_pipe.c 2001/09/20 16:26:56 1.13 @@ -38,22 +38,23 @@ #define L2_PIPE_MAXARGS 256 /* shell command execution */ static l2_result_t hook_open(l2_context_t *, l2_channel_t *); /* prototypes */ +static l2_result_t hook_close(l2_context_t *, l2_channel_t *); /* declare private channel configuration */ typedef struct { - int piFd[2]; /* pipe file descriptor */ - int iMode; /* execution mode direct or shell */ - pid_t Pid; /* pid set during fork in hook_open() */ - char *szCmdpath; /* path to command and arguments */ + int piFd[2]; /* pipe file descriptor */ + int iChild; /* exception status of child pipe process */ + int iMode; /* execution mode direct or shell */ + pid_t Pid; /* pid set during fork in hook_open() */ + char *szCmdpath; /* path to command and arguments */ } l2_ch_pipe_t; static void catchsignal(int sig, ...) { - int iStatus = 0; - va_list ap = NULL; - static l2_context_t *ctx = NULL; - static l2_channel_t *chan = NULL; + va_list ap = NULL; + static l2_context_t *ctx = NULL; + static l2_channel_t *chan = NULL; if (sig == 0) { va_start(ap, sig); @@ -63,15 +64,24 @@ } else if (sig == SIGCHLD) { /* TRACE("SIGCHLD caught\n");*/ - waitpid(((l2_ch_pipe_t *)ctx->vp)->Pid, &iStatus, 0); - close(((l2_ch_pipe_t *)ctx->vp)->piFd[1]); - ((l2_ch_pipe_t *)ctx->vp)->piFd[1] = -1; - if (hook_open(ctx, chan) != L2_OK) { /* TODO: Fix infinit loop! */ + waitpid(((l2_ch_pipe_t *)ctx->vp)->Pid, &((l2_ch_pipe_t *)ctx->vp)->iChild, WUNTRACED); + if (WIFEXITED(((l2_ch_pipe_t *)ctx->vp)->iChild)) { close(((l2_ch_pipe_t *)ctx->vp)->piFd[1]); ((l2_ch_pipe_t *)ctx->vp)->piFd[1] = -1; + ((l2_ch_pipe_t *)ctx->vp)->Pid = -1; + /* check if process called exit() abnormally, then if so restarts */ + if (WEXITSTATUS(((l2_ch_pipe_t *)ctx->vp)->iChild)) { + fprintf(stderr, "exit status is %d\n", WEXITSTATUS(((l2_ch_pipe_t *)ctx->vp)->iChild)); + if (hook_open(ctx, chan) != L2_OK) { /* TODO: Fix infinit loop! */ + close(((l2_ch_pipe_t *)ctx->vp)->piFd[1]); + ((l2_ch_pipe_t *)ctx->vp)->piFd[1] = -1; + } + } + } + else if (WIFSTOPPED(((l2_ch_pipe_t *)ctx->vp)->iChild)) { } } - else if (sig == SIGPIPE) { + else if (sig == SIGPIPE) { /* thrown when we write to child's closed pipe */ /* TRACE("SIGPIPE caught\n");*/ close(((l2_ch_pipe_t *)ctx->vp)->piFd[1]); ((l2_ch_pipe_t *)ctx->vp)->piFd[1] = -1; @@ -88,9 +98,11 @@ return L2_ERR_ARG; /* initialize configuration with reasonable defaults */ - cfg->piFd[0] = -1; - cfg->piFd[1] = -1; - cfg->iMode = -1; + cfg->piFd[0] = -1; + cfg->piFd[1] = -1; + cfg->iChild = 0; + cfg->iMode = -1; + cfg->Pid = -1; cfg->szCmdpath = NULL; /* link private channel configuration into channel context */ @@ -225,6 +237,13 @@ if (cfg->piFd[1] == -1) return L2_ERR_IO; + if (WIFSTOPPED(cfg->iChild)) { + if (kill(cfg->Pid, SIGCONT)) { + hook_close(ctx, ch); + cfg->iChild = 0; + return L2_ERR_SYS; + } + } /* write message to channel pipe */ else if (write(cfg->piFd[1], buf, buf_size) == -1) return L2_ERR_SYS; @@ -240,6 +259,9 @@ /* close channel pipe for parent process created in hook_open() */ close(cfg->piFd[1]); cfg->piFd[1] = -1; + if (kill(cfg->Pid, SIGTERM)) + return L2_ERR_SYS; + cfg->Pid = -1; return L2_OK; }