summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/connections.c5
-rw-r--r--src/mod_fastcgi.c239
-rw-r--r--src/response.c1
-rw-r--r--src/server.c1
4 files changed, 141 insertions, 105 deletions
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 */