]> granicus.if.org Git - apache/commitdiff
PID table impl: parent process keeps a local table store of
authorJim Jagielski <jim@apache.org>
Sat, 16 Jun 2007 21:29:24 +0000 (21:29 +0000)
committerJim Jagielski <jim@apache.org>
Sat, 16 Jun 2007 21:29:24 +0000 (21:29 +0000)
Apache child process PIDs and uses that to check validity
of what's in the scoreboard.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@547987 13f79535-47bb-0310-9956-ffa450edef68

18 files changed:
CHANGES
include/mpm_common.h
server/main.c
server/mpm/beos/mpm.h
server/mpm/experimental/event/event.c
server/mpm/experimental/event/mpm.h
server/mpm/experimental/leader/mpm.h
server/mpm/experimental/perchild/mpm.h
server/mpm/experimental/threadpool/mpm.h
server/mpm/mpmt_os2/mpm.h
server/mpm/mpmt_os2/mpmt_os2.c
server/mpm/netware/mpm.h
server/mpm/prefork/mpm.h
server/mpm/prefork/prefork.c
server/mpm/worker/mpm.h
server/mpm/worker/worker.c
server/mpm_common.c
server/scoreboard.c

diff --git a/CHANGES b/CHANGES
index 85d652c09d3abcbec79e4dca461ccfc2c679e802..4870a3502dcbd9598f70117c55869cb2fd84d0ef 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,11 @@
 Changes with Apache 2.3.0
   [Remove entries to the current 2.0 and 2.2 section below, when backported]
 
+  *) mpm: Add a parent process local table of child process PIDs, and
+     use that to ensure we are sending signals to just our child
+     processes by checking the scoreboard PID entries to our local
+     copy. [Jim Jagielski]
+
   *) Event MPM: Add support for running under mod_ssl, by reverting to the
      Worker MPM behaviors, when run under an input filter that buffers
      its own data. [Paul Querna]
index 20a74ac6424d04c9f9d8d8597f09147765226703..1b69fb5e4cdb273dc7c6aa9a83c3a77cef6f638c 100644 (file)
@@ -349,6 +349,14 @@ extern const char *ap_mpm_set_exception_hook(cmd_parms *cmd, void *dummy,
                                              const char *arg);
 #endif
 
+/*
+ * The parent process pid table
+ */
+extern apr_table_t *ap_pid_table;
+int ap_in_pid_table(pid_t pid);
+void ap_set_pid_table(pid_t pid);
+void ap_unset_pid_table(pid_t pid);
+
 AP_DECLARE_HOOK(int,monitor,(apr_pool_t *p))
 
 #ifdef __cplusplus
index 7285eae1a0e08f3832d485e71324d9f3525c0219..f8a90a75f6eacfdcdcfe48fbee39754959aecefb 100644 (file)
@@ -480,6 +480,7 @@ int main(int argc, const char * const argv[])
     ap_server_pre_read_config  = apr_array_make(pcommands, 1, sizeof(char *));
     ap_server_post_read_config = apr_array_make(pcommands, 1, sizeof(char *));
     ap_server_config_defines   = apr_array_make(pcommands, 1, sizeof(char *));
+    ap_pid_table               = apr_table_make(pglobal, 1024);
 
     error = ap_setup_prelinked_modules(process);
     if (error) {
index d61594b0603ab1b4aa3b506f81998b0dc2a8af30..cadf36521a0063fb5946028ae9af3685d375383f 100644 (file)
 
 #define MPM_NAME "Beos"
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->servers[0][i].tid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_NOTE_CHILD_KILLED(i) do {         \
+        ap_unset_pid_table(MPM_CHILD_PID(i)); \
+        MPM_CHILD_PID(i) = 0;                 \
+    } while(0) 
 
 #define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
 #define AP_MPM_WANT_WAIT_OR_TIMEOUT
index 9d242b3867e6f84aec135fc1dce57e576673b302..be4b4b7d85a70bc40b6577eff36f34657a65de6f 100644 (file)
@@ -1652,6 +1652,7 @@ static int make_child(server_rec * s, int slot)
     /* else */
     ap_scoreboard_image->parent[slot].quiescing = 0;
     ap_scoreboard_image->parent[slot].pid = pid;
+    ap_set_pid_table(pid);
     return 0;
 }
 
@@ -2071,10 +2072,12 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
             active_children = 0;
             for (index = 0; index < ap_daemons_limit; ++index) {
                 if (MPM_CHILD_PID(index) != 0) {
-                    if (kill(MPM_CHILD_PID(index), 0) == 0) {
+                    if (ap_in_pid_table(MPM_CHILD_PID(index))) {
+                        if (kill(MPM_CHILD_PID(index), 0) == 0) {
                             active_children = 1;
                             /* Having just one child is enough to stay around */
                             break;
+                        }
                     }
                 }
             }
index cf4e61d911519b6d22028b754e4db4c16f3fef09..c2731afd8c9962a79c2dd5e9e5a6ef8470720b2b 100644 (file)
 #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
 
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_NOTE_CHILD_KILLED(i) do {         \
+        ap_unset_pid_table(MPM_CHILD_PID(i)); \
+        MPM_CHILD_PID(i) = 0;                 \
+    } while(0) 
 #define MPM_ACCEPT_FUNC unixd_accept
 
 extern int ap_threads_per_child;
index d30be86a1fd0536f49a14edb06e6fee5966ff9d0..680c9ca6912cd0ad5a476b686734c61d128b234a 100644 (file)
 
 #define AP_MPM_USES_POD 1
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_NOTE_CHILD_KILLED(i) do {         \
+        ap_unset_pid_table(MPM_CHILD_PID(i)); \
+        MPM_CHILD_PID(i) = 0;                 \
+    } while(0) 
 #define MPM_ACCEPT_FUNC unixd_accept
 
 extern int ap_threads_per_child;
index af9723872871c2a1dfec16e0cbbe00465ad92e75..c54863efe390443b6b601aa76e6b788767a6dc0f 100644 (file)
 #define AP_MPM_USES_POD
 
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_NOTE_CHILD_KILLED(i) do {         \
+        ap_unset_pid_table(MPM_CHILD_PID(i)); \
+        MPM_CHILD_PID(i) = 0;                 \
+    } while(0) 
 #define MPM_ACCEPT_FUNC unixd_accept
 
 /* Table of child status */
index 806011b88570498a1c147776cce62d73c2c644f1..624f37c89a56d61c796416fc7bd332bf094633f6 100644 (file)
 #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
 
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_NOTE_CHILD_KILLED(i) do {         \
+        ap_unset_pid_table(MPM_CHILD_PID(i)); \
+        MPM_CHILD_PID(i) = 0;                 \
+    } while(0) 
 #define MPM_ACCEPT_FUNC unixd_accept
 
 extern int ap_threads_per_child;
index f8bbc30eb38c96245a816ec5bd489357c0b5ac17..e324d79a387fb84479a8d85e9425552f7afdee49 100644 (file)
@@ -30,6 +30,7 @@
 #include "httpd.h"
 #include "mpm_default.h"
 #include "scoreboard.h"
+#include "mpm_common.h"
 
 #define MPM_NAME "MPMT_OS2"
 
index a5636cefda0b8c7dc957a5bbc08f859e35997783..1d4a43d4b0592661348b83a054e0c8164613494c 100644 (file)
@@ -281,6 +281,7 @@ static char master_main()
 #endif
     if (one_process) {
         ap_scoreboard_image->parent[0].pid = getpid();
+        ap_set_pid_table(getpid());
         ap_mpm_child_main(pconf);
         return FALSE;
     }
@@ -307,6 +308,7 @@ static char master_main()
         rc = DosWaitChild(DCWA_PROCESSTREE, DCWW_NOWAIT, &proc_rc, &child_pid, 0);
 
         if (rc == 0) {
+            ap_unset_pid_table(child_pid);
             /* A child has terminated, remove its scoreboard entry & terminate if necessary */
             for (slot=0; ap_scoreboard_image->parent[slot].pid != child_pid && slot < HARD_SERVER_LIMIT; slot++);
 
@@ -330,7 +332,13 @@ static char master_main()
 
     /* Signal children to shut down, either gracefully or immediately */
     for (slot=0; slot<HARD_SERVER_LIMIT; slot++) {
-      kill(ap_scoreboard_image->parent[slot].pid, is_graceful ? SIGHUP : SIGTERM);
+        PID pid;
+
+        pid = ap_scoreboard_image->parent[n].pid;
+        if (ap_in_pid_table(pid)) {
+            kill(pid, is_graceful ? SIGHUP : SIGTERM);
+            ap_unset_pid_table(pid);
+        }
     }
 
     DosFreeMem(parent_info);
@@ -364,6 +372,7 @@ static void spawn_child(int slot)
     }
 
     ap_scoreboard_image->parent[slot].pid = proc_rc.codeTerminate;
+    ap_set_pid_table(proc_rc.codeTerminate);
 }
 
 
index 106d62a5095894277d61d3134bad529c99b96ea7..93f1824e5a567714086ea73a5b6e32b60b88b7ad 100644 (file)
 */
 
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_NOTE_CHILD_KILLED(i) do {         \
+        ap_unset_pid_table(MPM_CHILD_PID(i)); \
+        MPM_CHILD_PID(i) = 0;                 \
+    } while(0) 
 
 extern int ap_threads_per_child;
 extern int ap_max_workers_limit;
index bf1fb949996fe8adc21b92ca8eacbe72dd8e27fc..51743d2ccaedc7e75b4fa609d7e7b90a094a3455 100644 (file)
 
 #define AP_MPM_USES_POD 1
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_NOTE_CHILD_KILLED(i) do {         \
+        ap_unset_pid_table(MPM_CHILD_PID(i)); \
+        MPM_CHILD_PID(i) = 0;                 \
+    } while(0) 
 #define MPM_ACCEPT_FUNC unixd_accept
 
 extern int ap_threads_per_child;
index 31c19df84f8d7d0bf2e023e301b71c7a20f357af..6a51f657f7d2b57648742b158e96e16845cb38f2 100644 (file)
@@ -305,13 +305,18 @@ int reap_children(int *exitcode, apr_exit_why_e *status)
     int n, pid;
 
     for (n = 0; n < ap_max_daemons_limit; ++n) {
-        if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&
-                kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
-            ap_update_child_status_from_indexes(n, 0, SERVER_DEAD, NULL);
-            /* just mark it as having a successful exit status */
-            *status = APR_PROC_EXIT;
-            *exitcode = 0;
-            return(pid);
+        pid = ap_scoreboard_image->parent[n].pid;
+        if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD) {
+            if (ap_in_pid_table(pid)) {
+                if (kill(pid, 0) == -1) {
+                    ap_update_child_status_from_indexes(n, 0, SERVER_DEAD, NULL);
+                    /* just mark it as having a successful exit status */
+                    *status = APR_PROC_EXIT;
+                    *exitcode = 0;
+                    ap_unset_pid_table(pid);
+                    return(pid);
+                }
+            }
         }
     }
     return 0;
@@ -737,6 +742,7 @@ static int make_child(server_rec *s, int slot)
     }
 
     ap_scoreboard_image->parent[slot].pid = pid;
+    ap_set_pid_table(pid);
 
     return 0;
 }
@@ -1119,8 +1125,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
         for (index = 0; index < ap_daemons_limit; ++index) {
             if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
                 /* Ask each child to close its listeners. */
-                kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
-                active_children++;
+                if (ap_in_pid_table(MPM_CHILD_PID(index))) {
+                    kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
+                    active_children++;
+                }
             }
         }
 
@@ -1158,10 +1166,12 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
             active_children = 0;
             for (index = 0; index < ap_daemons_limit; ++index) {
                 if (MPM_CHILD_PID(index) != 0) {
-                    if (kill(MPM_CHILD_PID(index), 0) == 0) {
+                    if (ap_in_pid_table(MPM_CHILD_PID(index))) {
+                        if (kill(MPM_CHILD_PID(index), 0) == 0) {
                             active_children = 1;
                             /* Having just one child is enough to stay around */
                             break;
+                        }
                     }
                 }
             }
@@ -1214,7 +1224,9 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
                  * piped loggers, etc. They almost certainly won't handle
                  * it gracefully.
                  */
-                kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
+                if (ap_in_pid_table(MPM_CHILD_PID(index))) {
+                    kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
+                }
             }
         }
     }
index 335f4b6ace40aef35162eb42749ff2c88b08a762..a8585d375ee6d59972123c62e2845847b26f6204 100644 (file)
 #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
 
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_NOTE_CHILD_KILLED(i) do {         \
+        ap_unset_pid_table(MPM_CHILD_PID(i)); \
+        MPM_CHILD_PID(i) = 0;                 \
+    } while(0) 
 #define MPM_ACCEPT_FUNC unixd_accept
 
 extern int ap_threads_per_child;
index e8eca8c197ad5391d12d3a6e01f71f8461c623a8..f7e6c56c10db7db50c2eeb2413603d9360bdb83d 100644 (file)
@@ -1360,6 +1360,8 @@ static int make_child(server_rec *s, int slot)
     }
     ap_scoreboard_image->parent[slot].quiescing = 0;
     ap_scoreboard_image->parent[slot].pid = pid;
+    ap_set_pid_table(pid);
+
     return 0;
 }
 
@@ -1600,6 +1602,7 @@ static void server_main_loop(int remaining_children_to_start)
                                                         (request_rec *) NULL);
 
                 ap_scoreboard_image->parent[child_slot].pid = 0;
+                ap_unset_pid_table(pid.pid);
                 ap_scoreboard_image->parent[child_slot].quiescing = 0;
                 if (processed_status == APEXIT_CHILDSICK) {
                     /* resource shortage, minimize the fork rate */
@@ -1816,10 +1819,12 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
             active_children = 0;
             for (index = 0; index < ap_daemons_limit; ++index) {
                 if (MPM_CHILD_PID(index) != 0) {
-                    if (kill(MPM_CHILD_PID(index), 0) == 0) {
+                    if (ap_in_pid_table(MPM_CHILD_PID(index))) {
+                        if (kill(MPM_CHILD_PID(index), 0) == 0) {
                             active_children = 1;
                             /* Having just one child is enough to stay around */
                             break;
+                        }
                     }
                 }
             }
index 832cc4084b427bc24c6480de89ca3591eab9c906..341f580bc42334fe1ac815d7f95bbfa81f74dd8c 100644 (file)
@@ -87,6 +87,41 @@ typedef struct extra_process_t {
 
 static extra_process_t *extras;
 
+/*
+ * Parent process local storage of child pids
+ */
+apr_table_t *ap_pid_table;
+
+/*
+ * Check the pid table to see if the actual pid exists
+ */
+int ap_in_pid_table(pid_t pid) {
+    char apid[64];
+    const char *spid;
+    apr_snprintf(apid, sizeof(apid), "%" APR_PID_T_FMT, pid);
+    spid = apr_table_get(ap_pid_table, apid);
+    if (spid && spid[0] == '1' && spid[1] == '\0')
+        return 1;
+    else {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
+                     "child process %" APR_PID_T_FMT
+                     " does not exist in local pid table", pid);
+        return 0;
+    }
+}
+
+void ap_set_pid_table(pid_t pid) {
+    char apid[64];
+    apr_snprintf(apid, sizeof(apid), "%" APR_PID_T_FMT, pid);
+    apr_table_set(ap_pid_table, apid, "1");
+}
+
+void ap_unset_pid_table(pid_t pid) {
+    char apid[64];
+    apr_snprintf(apid, sizeof(apid), "%" APR_PID_T_FMT, pid);
+    apr_table_unset(ap_pid_table, apid);
+}
+
 void ap_register_extra_mpm_process(pid_t pid)
 {
     extra_process_t *p = (extra_process_t *)malloc(sizeof(extra_process_t));
@@ -114,6 +149,7 @@ int ap_unregister_extra_mpm_process(pid_t pid)
             extras = cur->next;
         }
         free(cur);
+        ap_unset_pid_table(pid);
         return 1; /* found */
     }
     else {
@@ -128,6 +164,9 @@ static int reclaim_one_pid(pid_t pid, action_t action)
     apr_status_t waitret;
 
     proc.pid = pid;
+    if (!ap_in_pid_table(pid)) {
+        return 0;
+    }
     waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT);
     if (waitret != APR_CHILD_NOTDONE) {
         return 1;
index 99238bac236e1d015532c65f768d36bfa5e2150c..2e00452c95c7a4744e5f122307101c2991d6a858 100644 (file)
@@ -35,6 +35,7 @@
 #include "ap_mpm.h"
 
 #include "mpm.h"
+#include "mpm_common.h"
 #include "scoreboard.h"
 
 AP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL;
@@ -363,7 +364,8 @@ int find_child_by_pid(apr_proc_t *pid)
     ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_daemons_limit);
 
     for (i = 0; i < max_daemons_limit; ++i) {
-        if (ap_scoreboard_image->parent[i].pid == pid->pid) {
+        if (ap_scoreboard_image->parent[i].pid == pid->pid &&
+            ap_in_pid_table(pid->pid)) {
             return i;
         }
     }