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]
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
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) {
#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
/* else */
ap_scoreboard_image->parent[slot].quiescing = 0;
ap_scoreboard_image->parent[slot].pid = pid;
+ ap_set_pid_table(pid);
return 0;
}
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;
+ }
}
}
}
#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;
#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;
#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 */
#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;
#include "httpd.h"
#include "mpm_default.h"
#include "scoreboard.h"
+#include "mpm_common.h"
#define MPM_NAME "MPMT_OS2"
#endif
if (one_process) {
ap_scoreboard_image->parent[0].pid = getpid();
+ ap_set_pid_table(getpid());
ap_mpm_child_main(pconf);
return FALSE;
}
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++);
/* 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);
}
ap_scoreboard_image->parent[slot].pid = proc_rc.codeTerminate;
+ ap_set_pid_table(proc_rc.codeTerminate);
}
*/
#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;
#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;
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;
}
ap_scoreboard_image->parent[slot].pid = pid;
+ ap_set_pid_table(pid);
return 0;
}
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++;
+ }
}
}
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;
+ }
}
}
}
* 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);
+ }
}
}
}
#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;
}
ap_scoreboard_image->parent[slot].quiescing = 0;
ap_scoreboard_image->parent[slot].pid = pid;
+ ap_set_pid_table(pid);
+
return 0;
}
(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 */
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;
+ }
}
}
}
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));
extras = cur->next;
}
free(cur);
+ ap_unset_pid_table(pid);
return 1; /* found */
}
else {
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;
#include "ap_mpm.h"
#include "mpm.h"
+#include "mpm_common.h"
#include "scoreboard.h"
AP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL;
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;
}
}