OSSP CVS Repository

ossp - Check-in [1022]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 1022
Date: 2001-Sep-20 18:26:56 (local)
2001-Sep-20 16:26:56 (UTC)
User:ms
Branch:
Comment: Debugging of channel's behavior logic when facing problematic children.
Tickets:
Inspections:
Files:
ossp-pkg/l2/TODO      1.23 -> 1.24     2 inserted, 0 deleted
ossp-pkg/l2/l2.pod      1.6 -> 1.7     52 inserted, 0 deleted
ossp-pkg/l2/l2_ch_pipe.c      1.12 -> 1.13     38 inserted, 16 deleted

ossp-pkg/l2/TODO 1.23 -> 1.24

--- 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
 ------


ossp-pkg/l2/l2.pod 1.6 -> 1.7

--- 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<l2_handler_pipe> 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<command> (optional, C<char *>)
+
+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<l2_handler_smtp> sends the incoming


ossp-pkg/l2/l2_ch_pipe.c 1.12 -> 1.13

--- 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;
 }

CVSTrac 2.0.1