[mod_cgi] consolidate CGI cleanup code

(more consistent behavior)

From: Glenn Strauss <gstrauss@gluelogic.com>

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3090 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/heads/lighttpd-1.4.x
Glenn Strauss 2016-03-04 18:54:26 +00:00 committed by Stefan Bühler
parent 94647804cf
commit e5e66f791f
2 changed files with 26 additions and 109 deletions

1
NEWS
View File

@ -20,6 +20,7 @@ NEWS
* [plugins] don't include dlfcn.h if not needed (fixes #2548)
* [mod_fastcgi] 404 for X-Sendfile file not found (fixes #2474)
* [mod_cgi] send 500 if CGI ends and there is no response (fixes #2542)
* [mod_cgi] consolidate CGI cleanup code
- 1.4.39 - 2016-01-02
* [core] fix memset_s call (fixes #2698)

View File

@ -522,15 +522,8 @@ static int cgi_demux_response(server *srv, handler_ctx *hctx) {
static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) {
int status;
pid_t pid;
plugin_data *p;
connection *con;
if (NULL == hctx) return HANDLER_GO_ON;
p = hctx->plugin_data;
con = hctx->remote_conn;
if (con->mode != p->id) return HANDLER_GO_ON;
plugin_data *p = hctx->plugin_data;
connection *con = hctx->remote_conn;
#ifndef __WIN32
@ -631,8 +624,12 @@ static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) {
static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
plugin_data *p = p_d;
handler_ctx *hctx = con->plugin_ctx[p->id];
return cgi_connection_close(srv, con->plugin_ctx[p->id]);
if (con->mode != p->id) return HANDLER_GO_ON;
if (NULL == hctx) return HANDLER_GO_ON;
return cgi_connection_close(srv, hctx);
}
@ -642,12 +639,6 @@ static handler_t cgi_handle_fdevent(server *srv, void *ctx, int revents) {
joblist_append(srv, con);
if (hctx->fd == -1) {
log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
return HANDLER_ERROR;
}
if (revents & FDEVENT_IN) {
switch (cgi_demux_response(srv, hctx)) {
case FDEVENT_HANDLED_NOT_FINISHED:
@ -663,17 +654,10 @@ static handler_t cgi_handle_fdevent(server *srv, void *ctx, int revents) {
/* if we get a IN|HUP and have read everything don't exec the close twice */
return HANDLER_FINISHED;
case FDEVENT_HANDLED_ERROR:
/* Send an error if we haven't sent any data yet */
if (0 == con->file_started) {
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
con->http_status = 500;
con->mode = DIRECT;
} else {
con->file_finished = 1;
}
log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
break;
cgi_connection_close(srv, hctx);
return HANDLER_FINISHED;
}
}
@ -689,13 +673,6 @@ static handler_t cgi_handle_fdevent(server *srv, void *ctx, int revents) {
http_chunk_append_buffer(srv, con, hctx->response_header);
}
if (con->file_finished == 0) {
http_chunk_close(srv, con);
}
con->file_finished = 1;
joblist_append(srv, con);
# if 0
log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
# endif
@ -703,8 +680,6 @@ static handler_t cgi_handle_fdevent(server *srv, void *ctx, int revents) {
/* rtsigs didn't liked the close */
cgi_connection_close(srv, hctx);
} else if (revents & FDEVENT_ERR) {
con->file_finished = 1;
/* kill all connections to the cgi process */
cgi_connection_close(srv, hctx);
#if 1
@ -1212,18 +1187,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_unregister(srv->ev, hctx->fd);
log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
close(hctx->fd);
cgi_handler_ctx_free(hctx);
con->plugin_ctx[p->id] = NULL;
cgi_connection_close(srv, hctx);
return -1;
}
@ -1370,8 +1334,8 @@ TRIGGER_FUNC(cgi_trigger) {
/*
* - HANDLER_GO_ON : not our job
* - HANDLER_FINISHED: got response header
* - HANDLER_WAIT_FOR_EVENT: waiting for response header
* - HANDLER_FINISHED: got response
* - HANDLER_WAIT_FOR_EVENT: waiting for response
*/
SUBREQUEST_FUNC(mod_cgi_handle_subrequest) {
int status;
@ -1385,84 +1349,39 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) {
log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
#endif
if (hctx->pid == 0) {
/* cgi already dead */
if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
return HANDLER_FINISHED;
}
#ifndef __WIN32
switch(waitpid(hctx->pid, &status, WNOHANG)) {
case 0:
/* we only have for events here if we don't have the header yet,
* otherwise the event-handler will send us the incoming data */
if (con->file_started) return HANDLER_FINISHED;
return HANDLER_WAIT_FOR_EVENT;
case -1:
if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
if (errno == ECHILD && con->file_started == 0) {
/*
* second round but still not response
*/
return HANDLER_WAIT_FOR_EVENT;
}
log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
con->mode = DIRECT;
con->http_status = 500;
hctx->pid = 0;
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_unregister(srv->ev, hctx->fd);
if (close(hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
if (errno != ECHILD) {
log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
}
break;
cgi_handler_ctx_free(hctx);
con->plugin_ctx[p->id] = NULL;
return HANDLER_FINISHED;
default:
/* cgi process exited
*/
hctx->pid = 0;
if (!WIFEXITED(status)) {
log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
}
if (cgi_demux_response(srv, hctx) == FDEVENT_HANDLED_ERROR) {
log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
}
/* we already have response headers? just continue */
if (con->file_started) return HANDLER_FINISHED;
if (WIFEXITED(status)) {
/* clean exit - just continue */
return HANDLER_WAIT_FOR_EVENT;
}
/* cgi proc died, and we didn't get any data yet - send error message and close cgi con */
log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
con->http_status = 500;
con->mode = DIRECT;
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_unregister(srv->ev, hctx->fd);
if (close(hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
}
cgi_handler_ctx_free(hctx);
con->plugin_ctx[p->id] = NULL;
return HANDLER_FINISHED;
break;
}
cgi_connection_close(srv, hctx);
return HANDLER_FINISHED;
#else
return HANDLER_ERROR;
#endif
@ -1477,9 +1396,6 @@ int mod_cgi_plugin_init(plugin *p) {
p->connection_reset = cgi_connection_close_callback;
p->handle_subrequest_start = cgi_is_handled;
p->handle_subrequest = mod_cgi_handle_subrequest;
#if 0
p->handle_fdevent = cgi_handle_fdevent;
#endif
p->handle_trigger = cgi_trigger;
p->init = mod_cgi_init;
p->cleanup = mod_cgi_free;