New protocol to avoid too much sleep, improve performance while stress testing
1. procmgr_send_spawn_cmd() now return a status code from PM, so process handler now know the spawn request is denyed or not.
2. if a new process is created, no sleep is needed.
3. if no process is created, sleep a while
PR: 53693
Submitted by: Ryan Pan <panqingfeng gmail>
git-svn-id: https://svn.apache.org/repos/asf/httpd/mod_fcgid/trunk@1377398 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/modules/fcgid/fcgid_bridge.c b/modules/fcgid/fcgid_bridge.c
index fdefcc1..f0d9543 100644
--- a/modules/fcgid/fcgid_bridge.c
+++ b/modules/fcgid/fcgid_bridge.c
@@ -447,19 +447,19 @@
if (bucket_ctx->procnode)
break;
- /* Avoid sleeping the very first time through if there are no
- busy processes; the problem is just that we haven't spawned
- anything yet, so waiting is pointless */
- if (i > 0 || j > 0 || count_busy_processes(r, &fcgi_request)) {
- apr_sleep(apr_time_from_sec(1));
-
+ /* Send a spawn request if I can't get a process slot */
+ /* procmgr_send_spawn_cmd() return APR_SUCCESS if a process is created */
+ if( procmgr_send_spawn_cmd(&fcgi_request, r)==APR_SUCCESS ) {
bucket_ctx->procnode = apply_free_procnode(r, &fcgi_request);
if (bucket_ctx->procnode)
break;
}
-
- /* Send a spawn request if I can't get a process slot */
- procmgr_send_spawn_cmd(&fcgi_request, r);
+ else {
+ apr_sleep(apr_time_from_sec(1));
+ bucket_ctx->procnode = apply_free_procnode(r, &fcgi_request);
+ if (bucket_ctx->procnode)
+ break;
+ }
}
/* Connect to the fastcgi server */
diff --git a/modules/fcgid/fcgid_pm.h b/modules/fcgid/fcgid_pm.h
index b815a39..697c1a1 100644
--- a/modules/fcgid/fcgid_pm.h
+++ b/modules/fcgid/fcgid_pm.h
@@ -45,7 +45,10 @@
request_rec * r);
apr_status_t procmgr_fetch_cmd(fcgid_command * command,
server_rec * main_server);
-apr_status_t procmgr_finish_notify(server_rec * main_server);
+
+#define PROCMGR_PROC_CREATED 0
+#define PROCMGR_PROC_NOT_CREATED 1
+apr_status_t procmgr_finish_notify(server_rec * main_server, char proc_created);
apr_status_t procmgr_child_init(server_rec * main_server,
apr_pool_t * pchild);
diff --git a/modules/fcgid/fcgid_pm_main.c b/modules/fcgid/fcgid_pm_main.c
index 74e1888..7a04fd8 100644
--- a/modules/fcgid/fcgid_pm_main.c
+++ b/modules/fcgid/fcgid_pm_main.c
@@ -527,7 +527,7 @@
/* End of common to util_script.c */
-static void
+static apr_status_t
fastcgi_spawn(fcgid_command * command, server_rec * main_server,
apr_pool_t * configpool)
{
@@ -547,7 +547,7 @@
proctable_pm_unlock(main_server);
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, main_server,
"mod_fcgid: too much processes, please increase FCGID_MAX_APPLICATION");
- return;
+ return APR_CHILD_NOTDONE;
}
procnode = &proctable_array[free_list_header->next_index];
free_list_header->next_index = procnode->next_index;
@@ -589,7 +589,7 @@
ap_log_error(APLOG_MARK, APLOG_WARNING, rv, main_server,
"mod_fcgid: can't create pool for process");
- return;
+ return APR_CHILD_NOTDONE;
}
/* Set up longer, system defaults before falling into parsing fixed-limit
* request-by-request variables, so if any are overriden, they preempt
@@ -614,7 +614,7 @@
apr_pool_destroy(procnode->proc_pool);
link_node_to_list(main_server, free_list_header,
procnode, proctable_array);
- return;
+ return APR_CHILD_NOTDONE;
}
else {
/* The job done */
@@ -628,6 +628,7 @@
procnode->proc_id.pid);
register_spawn(main_server, procnode);
}
+ return APR_SUCCESS;
}
apr_status_t pm_main(server_rec * main_server, apr_pool_t * configpool)
@@ -635,15 +636,17 @@
fcgid_command command;
while (1) {
+ char proc_created = PROCMGR_PROC_NOT_CREATED;
if (procmgr_must_exit())
break;
/* Wait for command */
if (procmgr_fetch_cmd(&command, main_server) == APR_SUCCESS) {
if (is_spawn_allowed(main_server, &command))
- fastcgi_spawn(&command, main_server, configpool);
+ if( fastcgi_spawn(&command, main_server, configpool)==APR_SUCCESS )
+ proc_created = PROCMGR_PROC_CREATED;
- procmgr_finish_notify(main_server);
+ procmgr_finish_notify(main_server, proc_created);
}
/* Move matched node to error list */
diff --git a/modules/fcgid/fcgid_pm_unix.c b/modules/fcgid/fcgid_pm_unix.c
index 33d381b..ed5fa97 100644
--- a/modules/fcgid/fcgid_pm_unix.c
+++ b/modules/fcgid/fcgid_pm_unix.c
@@ -460,9 +460,10 @@
apr_status_t procmgr_send_spawn_cmd(fcgid_command * command,
request_rec * r)
{
- apr_status_t rv;
+ apr_status_t rv,result;
char notifybyte;
apr_size_t nbytes = sizeof(*command);
+ result = APR_SUCCESS;
/* Get the global mutex before posting the request */
if ((rv = apr_global_mutex_lock(g_pipelock)) != APR_SUCCESS) {
@@ -477,6 +478,7 @@
/* Just print some error log and fall through */
ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r,
"mod_fcgid: can't write spawn command");
+ result = rv;
} else {
/* Wait the finish notify while send the request successfully */
nbytes = sizeof(notifybyte);
@@ -485,7 +487,9 @@
&nbytes)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r,
"mod_fcgid: can't get notify from process manager");
- }
+ result = rv;
+ } else if( nbytes!=PROCMGR_PROC_CREATED )
+ result = APR_CHILD_NOTDONE;
}
/* Release the lock */
@@ -495,17 +499,16 @@
exit(0);
}
- return APR_SUCCESS;
+ return result;
}
-apr_status_t procmgr_finish_notify(server_rec * main_server)
+apr_status_t procmgr_finish_notify(server_rec * main_server, char proc_created)
{
apr_status_t rv;
- char notifybyte = 'p';
- apr_size_t nbytes = sizeof(notifybyte);
+ apr_size_t nbytes = sizeof(proc_created);
if ((rv =
- apr_file_write(g_pm_write_pipe, ¬ifybyte,
+ apr_file_write(g_pm_write_pipe, &proc_created,
&nbytes)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_WARNING, rv, main_server,
"mod_fcgid: can't send notify from process manager");
diff --git a/modules/fcgid/fcgid_pm_win.c b/modules/fcgid/fcgid_pm_win.c
index 77e661e..f6cff87 100644
--- a/modules/fcgid/fcgid_pm_win.c
+++ b/modules/fcgid/fcgid_pm_win.c
@@ -159,6 +159,7 @@
apr_status_t procmgr_send_spawn_cmd(fcgid_command * command,
request_rec * r)
{
+ char *notifybyte = NULL;
if (g_thread && g_msgqueue && !g_must_exit
&& g_reqlock && g_notifyqueue) {
apr_status_t rv;
@@ -189,8 +190,6 @@
return rv;
} else {
/* Wait the respond from process manager */
- char *notifybyte = NULL;
-
if ((rv =
apr_queue_pop(g_notifyqueue,
(void **)¬ifybyte)) != APR_SUCCESS) {
@@ -210,13 +209,22 @@
}
}
- return APR_SUCCESS;
+ if( notifybyte && *notifybyte==PROCMGR_PROC_CREATED )
+ return APR_SUCCESS;
+ else
+ return APR_CHILD_NOTDONE;
}
-apr_status_t procmgr_finish_notify(server_rec * main_server)
+static char g_proc_created = PROCMGR_PROC_CREATED;
+static char g_proc_not_created = PROCMGR_PROC_NOT_CREATED;
+apr_status_t procmgr_finish_notify(server_rec * main_server, char proc_created)
{
apr_status_t rv;
char *notify = NULL;
+ if( proc_created==PROCMGR_PROC_CREATED )
+ notify = &g_proc_created;
+ else
+ notify = &g_proc_not_created;
if ((rv = apr_queue_push(g_notifyqueue, notify)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, main_server,