172 |
172 |
173 Event *stderr_readev = pool_malloc(sn->pool, sizeof(Event)); |
173 Event *stderr_readev = pool_malloc(sn->pool, sizeof(Event)); |
174 ZERO(stderr_readev, sizeof(Event)); |
174 ZERO(stderr_readev, sizeof(Event)); |
175 stderr_readev->cookie = handler; |
175 stderr_readev->cookie = handler; |
176 stderr_readev->fn = cgi_stderr_readevent; |
176 stderr_readev->fn = cgi_stderr_readevent; |
177 stderr_readev->finish = NULL; |
177 stderr_readev->finish = cgi_event_finish; |
178 |
178 |
179 Event *writeev = pool_malloc(sn->pool, sizeof(Event)); |
179 Event *writeev = pool_malloc(sn->pool, sizeof(Event)); |
180 ZERO(writeev, sizeof(Event)); |
180 ZERO(writeev, sizeof(Event)); |
181 writeev->cookie = handler; |
181 writeev->cookie = handler; |
|
182 writeev->fn = cgi_writeevent; |
|
183 writeev->finish = cgi_event_finish; |
182 |
184 |
183 |
185 |
184 handler->writeev = writeev; |
186 handler->writeev = writeev; |
185 handler->stderrev = stderr_readev; |
|
186 |
187 |
187 net_setnonblock(sn->csd, 1); |
188 net_setnonblock(sn->csd, 1); |
188 |
189 |
189 // add poll events for cgi stdout/stderr |
190 // add poll events for cgi stdout/stderr |
190 int error = 0; |
191 int error = 0; |
194 } |
195 } |
195 if(ev_pollin(sn->ev, handler->process.out[0], readev)) { |
196 if(ev_pollin(sn->ev, handler->process.out[0], readev)) { |
196 log_ereport(LOG_FAILURE, "send-cgi: stdout ev_pollin failed"); |
197 log_ereport(LOG_FAILURE, "send-cgi: stdout ev_pollin failed"); |
197 error = 1; |
198 error = 1; |
198 } |
199 } |
|
200 |
|
201 handler->events = 2; // 2 events (stdout, stderr) |
199 |
202 |
200 if(error) { |
203 if(error) { |
201 log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", path); |
204 log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", path); |
202 kill(handler->process.pid, SIGKILL); |
205 kill(handler->process.pid, SIGKILL); |
203 cgi_parser_free(handler->parser); |
206 cgi_parser_free(handler->parser); |
256 if(!handler->poll_out) { |
259 if(!handler->poll_out) { |
257 if(event_pollout(ev, sn->csd, handler->writeev)) { |
260 if(event_pollout(ev, sn->csd, handler->writeev)) { |
258 handler->result = REQ_ABORTED; |
261 handler->result = REQ_ABORTED; |
259 return 0; |
262 return 0; |
260 } |
263 } |
|
264 handler->events++; |
261 handler->poll_out = TRUE; |
265 handler->poll_out = TRUE; |
262 } |
266 } |
263 } else { |
267 } else { |
264 handler->result = REQ_ABORTED; |
268 handler->result = REQ_ABORTED; |
265 log_ereport(LOG_FAILURE, "cgi_try_write: %s", strerror(errno)); |
269 log_ereport(LOG_FAILURE, "cgi_try_write: %s", strerror(errno)); |
454 } |
457 } |
455 |
458 |
456 if(handler->stderr_tmp) { |
459 if(handler->stderr_tmp) { |
457 pool_free(handler->parser->sn->pool, handler->stderr_tmp); |
460 pool_free(handler->parser->sn->pool, handler->stderr_tmp); |
458 } |
461 } |
459 handler->stderr_finished = TRUE; |
|
460 return 0; |
462 return 0; |
461 } |
463 } |
462 |
464 |
463 int cgi_event_finish(EventHandler *ev, Event *event) { |
465 int cgi_event_finish(EventHandler *ev, Event *event) { |
464 CGIHandler *handler = event->cookie; |
466 CGIHandler *handler = event->cookie; |
465 CGIResponseParser *parser = handler->parser; |
467 CGIResponseParser *parser = handler->parser; |
466 Session *sn = parser->sn; |
468 Session *sn = parser->sn; |
467 Request *rq = parser->rq; |
469 Request *rq = parser->rq; |
468 |
470 |
469 log_ereport(LOG_DEBUG, "cgi-send: req: %p event-finish", rq); |
471 log_ereport(LOG_DEBUG, "cgi-send: req: %p event-finish %d", rq, handler->events); |
|
472 if(--handler->events > 0) { |
|
473 return 0; |
|
474 } |
|
475 |
470 if(handler->result == REQ_ABORTED && handler->process.pid != 0) { |
476 if(handler->result == REQ_ABORTED && handler->process.pid != 0) { |
471 log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", handler->path); |
477 log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", handler->path); |
472 |
|
473 killpg(handler->process.pid, SIGTERM); |
478 killpg(handler->process.pid, SIGTERM); |
474 |
479 } |
475 handler->process.pid = 0; |
480 |
476 } |
481 log_ereport(LOG_DEBUG, "cgi-send: req: %p cgi_close", rq); |
477 |
|
478 if(!handler->stderr_finished) { |
|
479 // stderr handler is still active |
|
480 // set stderr event finish function, to run the finish code later |
|
481 handler->stderrev->finish = cgi_event_finish; |
|
482 return 0; |
|
483 } |
|
484 if(handler->poll_out && !handler->send_response_finished) { |
|
485 // send response is still active |
|
486 handler->writeev->finish = cgi_event_finish; |
|
487 return 0; |
|
488 } |
|
489 |
482 |
490 int exit_code = cgi_close(&handler->process); |
483 int exit_code = cgi_close(&handler->process); |
491 if(exit_code != 0) { |
484 if(exit_code != 0) { |
492 log_ereport(LOG_FAILURE, "send-cgi: script: %s exited with code %d", handler->path, exit_code); |
485 log_ereport(LOG_FAILURE, "send-cgi: script: %s exited with code %d", handler->path, exit_code); |
493 handler->result = REQ_ABORTED; |
486 handler->result = REQ_ABORTED; |