Hi!
Im working on some hosting company, where we intensively use mod_fcgid
as gateway for php. As evereybody knows php is bagy and faulty, ending
very often with segfult. The my idea is to restart fcgi app, when it
accepted request, made some processing, and for example ended with
segfault. Then fcgi_bridge (in handle_request) sould resend request
to new creating fcgi app. Then if this faild too, should finish as usual
- with 500 internal server error.
I attached simple patch to demostrate this idea.
I will be appreciate for any suggestion, if this idea is correct, or
maybe some have better concept of this.
ps. Sorry for my english.
--- fcgid_bridge.c.safe 2009-12-15 17:18:16.000000000 +0100
+++ fcgid_bridge.c 2010-08-06 19:20:18.000000000 +0200
@@ -281,25 +281,11 @@
return 1;
}
-static int
-handle_request(request_rec * r, int role, const char *argv0,
- fcgid_wrapper_conf * wrapper_conf,
- apr_bucket_brigade * output_brigade)
+static inline void apply_free_procslot(fcgid_wrapper_conf *wrapper_conf,fcgid_bucket_ctx *bucket_ctx,
+ const char *argv0,request_rec *r)
{
- apr_pool_t *request_pool = r->main ? r->main->pool : r->pool;
fcgid_command fcgi_request;
- fcgid_bucket_ctx *bucket_ctx;
- int i, j, cond_status;
- apr_status_t rv;
- apr_bucket_brigade *brigade_stdout;
- char sbuf[MAX_STRING_LEN];
- const char *location;
-
- bucket_ctx = apr_pcalloc(request_pool, sizeof(*bucket_ctx));
-
- bucket_ctx->ipc.request = r;
- apr_pool_cleanup_register(request_pool, bucket_ctx,
- bucket_ctx_cleanup, apr_pool_cleanup_null);
+ int i,j;
/* Try to get a connected ipc handle */
for (i = 0; i < FCGID_REQUEST_COUNT; i++) {
@@ -354,6 +340,32 @@
break;
}
}
+}
+
+static int
+handle_request(request_rec * r, int role, const char *argv0,
+ fcgid_wrapper_conf * wrapper_conf,
+ apr_bucket_brigade * output_brigade)
+{
+ apr_pool_t *request_pool = r->main ? r->main->pool : r->pool;
+ fcgid_bucket_ctx *bucket_ctx;
+ int cond_status;
+ int cur_probes,max_probes = 2;
+ apr_status_t rv;
+ apr_bucket_brigade *brigade_stdout;
+ char sbuf[MAX_STRING_LEN];
+ const char *location;
+
+ cur_probes = max_probes;
+
+ bucket_ctx = apr_pcalloc(request_pool, sizeof(*bucket_ctx));
+
+ bucket_ctx->ipc.request = r;
+ apr_pool_cleanup_register(request_pool, bucket_ctx,
+ bucket_ctx_cleanup, apr_pool_cleanup_null);
+
+spawn_retry:
+ apply_free_procslot(wrapper_conf,bucket_ctx,argv0,r);
/* Now I get a connected ipc handle */
if (!bucket_ctx->procnode) {
@@ -373,18 +385,27 @@
}
/* Create brigade */
- brigade_stdout =
- apr_brigade_create(request_pool, r->connection->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(brigade_stdout,
- ap_bucket_fcgid_header_create(r->connection->
- bucket_alloc,
- bucket_ctx));
+ if(!(cur_probes%max_probes)) {
+ brigade_stdout =
+ apr_brigade_create(request_pool, r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(brigade_stdout,
+ ap_bucket_fcgid_header_create(r->connection->
+ bucket_alloc,
+ bucket_ctx));
+ }
/*APR_BRIGADE_INSERT_TAIL(brigade_stdout, apr_bucket_flush_create(r->connection->bucket_alloc)); */
/* Check the script header first. If got error, return immediately */
if ((cond_status = ap_scan_script_header_err_core
- (r, sbuf, getsfunc_fcgid_BRIGADE, brigade_stdout)) >= 400)
+ (r, sbuf, getsfunc_fcgid_BRIGADE, brigade_stdout)) >= 400) {
+ if(--cur_probes && cond_status == HTTP_INTERNAL_SERVER_ERROR) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, r->server,
+ "OGC: fcgi app lost, retrying... (%s)",argv0);
+ return_procnode(r,bucket_ctx->procnode,1 /* has error */);
+ goto spawn_retry;
+ }
return cond_status;
+ }
/* Check redirect */
location = apr_table_get(r->headers_out, "Location");