# HG changeset patch # User Olaf Wintermann # Date 1685984603 -7200 # Node ID ef77854a91f371edb2486a6b2178ae89ae6be3be # Parent 0d80f8a2b29fa3cd1dbff327233c2908cdc9c841 fix cgi event handling, pipes were not always closed diff -r 0d80f8a2b29f -r ef77854a91f3 src/server/safs/cgi.c --- 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) { diff -r 0d80f8a2b29f -r ef77854a91f3 src/server/safs/cgi.h --- 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;