diff --git a/src/connections.c b/src/connections.c index dc3ed9f3..85004b7b 100644 --- a/src/connections.c +++ b/src/connections.c @@ -182,7 +182,7 @@ static void dump_packet(const unsigned char *data, size_t len) { fprintf(stderr, "\n"); } } -#endif // #if 0 +#endif static int connection_handle_read(server *srv, connection *con) { int len; @@ -1256,12 +1256,15 @@ int connection_state_machine(server *srv, connection *con) { connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); + done = 1; /* is this neccesary ? */ break; case HANDLER_COMEBACK: done = -1; case HANDLER_WAIT_FOR_EVENT: /* come back here */ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); + + done = 1; /* is this neccesary ? */ break; case HANDLER_ERROR: /* something went wrong */ diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 3e8cace4..ffc0c775 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -323,6 +323,9 @@ typedef struct { size_t path_info_offset; /* start of path_info in uri.path */ + pid_t pid; + int got_proc; + plugin_config conf; connection *remote_conn; /* dumb pointer */ @@ -1256,8 +1259,8 @@ void fcgi_connection_cleanup(server *srv, handler_ctx *hctx) { if (hctx->host && hctx->proc) { hctx->host->load--; - if (hctx->state != FCGI_STATE_INIT && - hctx->state != FCGI_STATE_CONNECT) { + + if (hctx->got_proc) { /* after the connect the process gets a load */ hctx->proc->load--; @@ -2246,6 +2249,92 @@ int fcgi_proclist_sort_down(server *srv, fcgi_extension_host *host, fcgi_proc *p return 0; } +static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) { + fcgi_proc *proc; + + for (proc = host->first; proc; proc = proc->next) { + if (p->conf.debug) { + log_error_write(srv, __FILE__, __LINE__, "sbdbdddd", + "proc:", + host->host, proc->port, + proc->socket, + proc->state, + proc->is_local, + proc->load, + proc->pid); + } + + if (0 == proc->is_local) { + /* + * external servers might get disabled + * + * enable the server again, perhaps it is back again + */ + + if ((proc->state == PROC_STATE_DISABLED) && + (srv->cur_ts - proc->disable_ts > FCGI_RETRY_TIMEOUT)) { + proc->state = PROC_STATE_RUNNING; + host->active_procs++; + + log_error_write(srv, __FILE__, __LINE__, "sbdb", + "fcgi-server re-enabled:", + host->host, host->port, + host->unixsocket); + } + } else { + /* the child should not terminate at all */ + int status; + + if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) { + switch(waitpid(proc->pid, &status, WNOHANG)) { + case 0: + /* child is still alive */ + break; + case -1: + break; + default: + if (WIFEXITED(status)) { +#if 0 + log_error_write(srv, __FILE__, __LINE__, "sdsd", + "child exited, pid:", proc->pid, + "status:", WEXITSTATUS(status)); +#endif + } else if (WIFSIGNALED(status)) { + log_error_write(srv, __FILE__, __LINE__, "sd", + "child signaled:", + WTERMSIG(status)); + } else { + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", + status); + } + + proc->state = PROC_STATE_DIED; + break; + } + } + + /* + * local servers might died, but we restart them + * + */ + if (proc->state == PROC_STATE_DIED && + proc->load == 0) { + /* restart the child */ + + if (fcgi_spawn_connection(srv, p, host, proc)) { + log_error_write(srv, __FILE__, __LINE__, "s", + "ERROR: spawning fcgi failed."); + return HANDLER_ERROR; + } + + fcgi_proclist_sort_down(srv, host, proc); + } + } + } + + return 0; +} static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { @@ -2303,6 +2392,9 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { return HANDLER_ERROR; } + if (hctx->proc->is_local) { + hctx->pid = hctx->proc->pid; + } switch (fcgi_establish_connection(srv, hctx)) { case 1: @@ -2310,6 +2402,8 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { /* connection is in progress, wait for an event and call getsockopt() below */ + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; case -1: /* if ECONNREFUSED choose another connection -> FIXME */ @@ -2334,9 +2428,13 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { return HANDLER_ERROR; } if (socket_error != 0) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "establishing connection failed:", strerror(socket_error), - "port:", hctx->proc->port); + if (!hctx->proc->is_local) { + /* local procs get restarted */ + + log_error_write(srv, __FILE__, __LINE__, "ss", + "establishing connection failed:", strerror(socket_error), + "port:", hctx->proc->port); + } return HANDLER_ERROR; } @@ -2346,6 +2444,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { hctx->proc->load++; hctx->proc->last_used = srv->cur_ts; + hctx->got_proc = 1; if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sddbdd", @@ -2377,11 +2476,13 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { /* fall through */ case FCGI_STATE_WRITE: - /* continue with the code after the switch */ - if (-1 == (r = write(hctx->fd, - hctx->write_buffer->ptr + hctx->write_offset, - hctx->write_buffer->used - hctx->write_offset))) { - + /* why aren't we using the network_ interface here ? */ + + r = write(hctx->fd, + hctx->write_buffer->ptr + hctx->write_offset, + hctx->write_buffer->used - hctx->write_offset); + + if (-1 == r) { if (errno == ENOTCONN) { /* the connection got dropped after accept() * @@ -2411,8 +2512,6 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { "write-offset:", hctx->write_offset, "reconnect attempts:", hctx->reconnects); - - return HANDLER_ERROR; } @@ -2424,6 +2523,8 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { return HANDLER_ERROR; } else { + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; } } @@ -2437,6 +2538,9 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { break; case FCGI_STATE_READ: /* waiting for a response */ + + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); + break; default: log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state"); @@ -2446,91 +2550,6 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { return HANDLER_WAIT_FOR_EVENT; } -static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) { - fcgi_proc *proc; - - for (proc = host->first; proc; proc = proc->next) { - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sbdbdddd", - "proc:", - host->host, proc->port, - proc->socket, - proc->state, - proc->is_local, - proc->load, - proc->pid); - } - - if (0 == proc->is_local) { - /* - * external servers might get disabled - * - * enable the server again, perhaps it is back again - */ - - if ((proc->state == PROC_STATE_DISABLED) && - (srv->cur_ts - proc->disable_ts > FCGI_RETRY_TIMEOUT)) { - proc->state = PROC_STATE_RUNNING; - host->active_procs++; - - log_error_write(srv, __FILE__, __LINE__, "sbdb", - "fcgi-server re-enabled:", - host->host, host->port, - host->unixsocket); - } - } else { - /* the child should not terminate at all */ - int status; - - if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) { - switch(waitpid(proc->pid, &status, WNOHANG)) { - case 0: - /* child is still alive */ - break; - case -1: - break; - default: - if (WIFEXITED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sdsd", - "child exited, pid:", proc->pid, - "status:", WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child signaled:", - WTERMSIG(status)); - } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", - status); - } - - proc->state = PROC_STATE_DIED; - break; - } - } - - /* - * local servers might died, but we restart them - * - */ - if (proc->state == PROC_STATE_DIED && - proc->load == 0) { - /* restart the child */ - - if (fcgi_spawn_connection(srv, p, host, proc)) { - log_error_write(srv, __FILE__, __LINE__, "s", - "ERROR: spawning fcgi failed."); - return HANDLER_ERROR; - } - - fcgi_proclist_sort_down(srv, host, proc); - } - } - } - - return 0; -} - SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { plugin_data *p = p_d; @@ -2571,14 +2590,28 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { * restart the request-handling */ if (proc && proc->is_local) { +#if 0 log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to fastcgi failed, restarting the request-handling:", host->host, proc->port, proc->socket); - proc->state = PROC_STATE_DIED_WAIT_FOR_PID; +#endif + /* + * several hctx might reference the same proc + * + * Only one of them should mark the proc as dead all the other + * ones should just take a new one. + * + * If a new proc was started with the old struct this might lead + * the mark a perfect proc as dead otherwise + * + */ + if (proc->state == PROC_STATE_RUNNING && + hctx->pid == proc->pid) { + proc->state = PROC_STATE_DIED_WAIT_FOR_PID; + } } - fcgi_restart_dead_procs(srv, p, host); fcgi_connection_cleanup(srv, hctx); @@ -2586,15 +2619,12 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { buffer_reset(con->physical.path); con->mode = DIRECT; - joblist_append(srv, con); - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop * and hope that the childs will be restarted * */ return HANDLER_WAIT_FOR_FD; } else { - fcgi_connection_cleanup(srv, hctx); buffer_reset(con->physical.path); @@ -2682,8 +2712,11 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { return HANDLER_FINISHED; case -1: - if (proc->pid) { + if (proc->pid && proc->state != PROC_STATE_DIED) { int status; + + /* only fetch the zombie if it is not already done */ + switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child is still alive */ diff --git a/src/response.c b/src/response.c index 1d0c5b15..e4416417 100644 --- a/src/response.c +++ b/src/response.c @@ -1242,7 +1242,6 @@ handler_t http_response_prepare(server *srv, connection *con) { switch(r = plugins_call_handle_subrequest(srv, con)) { case HANDLER_GO_ON: /* request was not handled, looks like we are done */ - return HANDLER_FINISHED; case HANDLER_FINISHED: /* request is finished */ diff --git a/src/server.c b/src/server.c index 0b109a9a..044c1659 100644 --- a/src/server.c +++ b/src/server.c @@ -952,6 +952,7 @@ int main (int argc, char **argv) { case HANDLER_FINISHED: case HANDLER_GO_ON: case HANDLER_WAIT_FOR_EVENT: + case HANDLER_WAIT_FOR_FD: break; case HANDLER_ERROR: /* should never happen */