|
|
|
@ -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]; |
|
|
|
|
|
|
|
|
|
if (con->mode != p->id) return HANDLER_GO_ON; |
|
|
|
|
if (NULL == hctx) return HANDLER_GO_ON; |
|
|
|
|
|
|
|
|
|
return cgi_connection_close(srv, con->plugin_ctx[p->id]); |
|
|
|
|
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 (cgi_demux_response(srv, hctx) == FDEVENT_HANDLED_ERROR) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: "); |
|
|
|
|
if (!WIFEXITED(status)) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* 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)); |
|
|
|
|
if (cgi_demux_response(srv, hctx) == FDEVENT_HANDLED_ERROR) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: "); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|