fix cgi event handling, pipes were not always closed

Mon, 05 Jun 2023 19:03:23 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 05 Jun 2023 19:03:23 +0200
changeset 499
ef77854a91f3
parent 498
0d80f8a2b29f
child 500
077aa138e8fb

fix cgi event handling, pipes were not always closed

src/server/safs/cgi.c file | annotate | diff | comparison | revisions
src/server/safs/cgi.h file | annotate | diff | comparison | revisions
--- a/src/server/safs/cgi.c	Sun Jun 04 20:09:18 2023 +0200
+++ b/src/server/safs/cgi.c	Mon Jun 05 19:03:23 2023 +0200
@@ -174,15 +174,16 @@
     ZERO(stderr_readev, sizeof(Event));
     stderr_readev->cookie = handler;
     stderr_readev->fn = cgi_stderr_readevent;
-    stderr_readev->finish = NULL;
+    stderr_readev->finish = cgi_event_finish;
     
     Event *writeev = pool_malloc(sn->pool, sizeof(Event));
     ZERO(writeev, sizeof(Event));
     writeev->cookie = handler;
+    writeev->fn = cgi_writeevent;
+    writeev->finish = cgi_event_finish;
     
     
     handler->writeev = writeev;
-    handler->stderrev = stderr_readev;
     
     net_setnonblock(sn->csd, 1);
     
@@ -197,6 +198,8 @@
         error = 1;
     }
     
+    handler->events = 2; // 2 events (stdout, stderr)
+    
     if(error) {
         log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", path);
         kill(handler->process.pid, SIGKILL);
@@ -258,6 +261,7 @@
                     handler->result = REQ_ABORTED;
                     return 0;
                 }
+                handler->events++;
                 handler->poll_out = TRUE;
             }
         } else {
@@ -367,7 +371,6 @@
         return 1;
     }
     
-    handler->read_output_finished = TRUE;
     return 0;
 }
 
@@ -456,7 +459,6 @@
     if(handler->stderr_tmp) {
         pool_free(handler->parser->sn->pool, handler->stderr_tmp);
     }
-    handler->stderr_finished = TRUE;
     return 0;
 }
 
@@ -466,26 +468,17 @@
     Session *sn = parser->sn;
     Request *rq = parser->rq;
       
-    log_ereport(LOG_DEBUG, "cgi-send: req: %p event-finish", rq);
-    if(handler->result == REQ_ABORTED && handler->process.pid != 0) {
-        log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", handler->path);
-        
-        killpg(handler->process.pid, SIGTERM);
-
-        handler->process.pid = 0;
+    log_ereport(LOG_DEBUG, "cgi-send: req: %p event-finish %d", rq, handler->events);
+    if(--handler->events > 0) {
+        return 0;
     }
     
-    if(!handler->stderr_finished) {
-        // stderr handler is still active
-        // set stderr event finish function, to run the finish code later
-        handler->stderrev->finish = cgi_event_finish;
-        return 0;
+    if(handler->result == REQ_ABORTED && handler->process.pid != 0) {
+        log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", handler->path);
+        killpg(handler->process.pid, SIGTERM);
     }
-    if(handler->poll_out && !handler->send_response_finished) {
-        // send response is still active
-        handler->writeev->finish = cgi_event_finish;
-        return 0;
-    }
+    
+     log_ereport(LOG_DEBUG, "cgi-send: req: %p cgi_close", rq);
     
     int exit_code = cgi_close(&handler->process);
     if(exit_code != 0) {
--- a/src/server/safs/cgi.h	Sun Jun 04 20:09:18 2023 +0200
+++ b/src/server/safs/cgi.h	Mon Jun 05 19:03:23 2023 +0200
@@ -57,20 +57,65 @@
     CGIProcess process;
     CGIResponseParser *parser;
     HttpResponseWriter *response;
+    
+    /*
+     * request path (rq->vars path)
+     */
     char *path;
+    
+    /*
+     * event object prepared for pollout
+     * only activated if write returns EWOULDBLOCK
+     */
     Event *writeev;
-    Event *stderrev;
+    
+    /*
+     * temp buffer used for parsing stderr lines
+     */
     char *stderr_tmp;
+    /*
+     * current length of stderr_tmp
+     */
     int stderr_tmplen;
+    
+    /*
+     * allocation size of stderr_tmp
+     */
     int stderr_tmpalloc;
+    
+    /*
+     * output buffer
+     */
     char *writebuf;
+    
+    /*
+     * writebuf allocation size
+     */
     size_t writebuf_alloc;
+    
+    /*
+     * currently used size of writebuf
+     */
     size_t writebuf_size;
+    
+    /*
+     * current writebuf pos (writebuf_size - write_buf_pos = remaining)
+     */
     size_t writebuf_pos;
-    WSBool stderr_finished;
-    WSBool read_output_finished;
-    WSBool send_response_finished;
+    
+    /*
+     * poll_out event active
+     */
     WSBool poll_out;
+    
+    /*
+     * number of currently open events (stdout, stderr, [stdout])
+     */
+    int events;
+    
+    /*
+     * error indicator
+     */
     int result;
 } CGIHandler;
     

mercurial