]> granicus.if.org Git - apache/blobdiff - server/mpm_common.c
Fix wrong condition that may lead to NULL being set as 'Vary' header
[apache] / server / mpm_common.c
index e7af61db8a7bfdf12b5218e18714f6f190897aed..cb0fd3a20ec6bb97e9eb132b1c0e1a8a706b7ba6 100644 (file)
@@ -56,6 +56,8 @@
 #include <unistd.h>
 #endif
 
+APLOG_USE_MODULE(core);
+
 #if AP_ENABLE_EXCEPTION_HOOK
 APR_HOOK_STRUCT(
     APR_HOOK_LINK(fatal_exception)
@@ -63,9 +65,10 @@ APR_HOOK_STRUCT(
     APR_HOOK_LINK(drop_privileges)
     APR_HOOK_LINK(mpm)
     APR_HOOK_LINK(mpm_query)
-    APR_HOOK_LINK(mpm_note_child_killed)
     APR_HOOK_LINK(mpm_register_timed_callback)
     APR_HOOK_LINK(mpm_get_name)
+    APR_HOOK_LINK(end_generation)
+    APR_HOOK_LINK(child_status)
 )
 AP_IMPLEMENT_HOOK_RUN_ALL(int, fatal_exception,
                           (ap_exception_info_t *ei), (ei), OK, DECLINED)
@@ -75,13 +78,14 @@ APR_HOOK_STRUCT(
     APR_HOOK_LINK(drop_privileges)
     APR_HOOK_LINK(mpm)
     APR_HOOK_LINK(mpm_query)
-    APR_HOOK_LINK(mpm_note_child_killed)
     APR_HOOK_LINK(mpm_register_timed_callback)
     APR_HOOK_LINK(mpm_get_name)
+    APR_HOOK_LINK(end_generation)
+    APR_HOOK_LINK(child_status)
 )
 #endif
 AP_IMPLEMENT_HOOK_RUN_ALL(int, monitor,
-                          (apr_pool_t *p), (p), OK, DECLINED)
+                          (apr_pool_t *p, server_rec *s), (p, s), OK, DECLINED)
 AP_IMPLEMENT_HOOK_RUN_ALL(int, drop_privileges,
                           (apr_pool_t * pchild, server_rec * s),
                           (pchild, s), OK, DECLINED)
@@ -91,16 +95,68 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int, mpm,
 AP_IMPLEMENT_HOOK_RUN_FIRST(int, mpm_query,
                             (int query_code, int *result, apr_status_t *_rv),
                             (query_code, result, _rv), DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, mpm_note_child_killed,
-                            (int childnum),
-                            (childnum), APR_ENOTIMPL)
 AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, mpm_register_timed_callback,
                             (apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton),
                             (t, cbfn, baton), APR_ENOTIMPL)
+AP_IMPLEMENT_HOOK_VOID(end_generation,
+                       (server_rec *s, ap_generation_t gen),
+                       (s, gen))
+AP_IMPLEMENT_HOOK_VOID(child_status,
+                       (server_rec *s, pid_t pid, ap_generation_t gen, int slot, mpm_child_status status),
+                       (s,pid,gen,slot,status))
+
+/* hooks with no args are implemented last, after disabling APR hook probes */
+#if defined(APR_HOOK_PROBES_ENABLED)
+#undef APR_HOOK_PROBES_ENABLED
+#undef APR_HOOK_PROBE_ENTRY
+#define APR_HOOK_PROBE_ENTRY(ud,ns,name,args)
+#undef APR_HOOK_PROBE_RETURN
+#define APR_HOOK_PROBE_RETURN(ud,ns,name,rv,args)
+#undef APR_HOOK_PROBE_INVOKE
+#define APR_HOOK_PROBE_INVOKE(ud,ns,name,src,args)
+#undef APR_HOOK_PROBE_COMPLETE
+#define APR_HOOK_PROBE_COMPLETE(ud,ns,name,src,rv,args)
+#undef APR_HOOK_INT_DCL_UD
+#define APR_HOOK_INT_DCL_UD
+#endif
 AP_IMPLEMENT_HOOK_RUN_FIRST(const char *, mpm_get_name,
                             (void),
                             (), NULL)
 
+typedef struct mpm_gen_info_t {
+    APR_RING_ENTRY(mpm_gen_info_t) link;
+    int gen;          /* which gen? */
+    int active;       /* number of active processes */
+} mpm_gen_info_t;
+
+APR_RING_HEAD(mpm_gen_info_head_t, mpm_gen_info_t);
+static struct mpm_gen_info_head_t geninfo, unused_geninfo;
+static int gen_head_init; /* yuck */
+
+/* variables representing config directives implemented here */
+const char *ap_pid_fname;
+int ap_max_requests_per_child;
+char ap_coredump_dir[MAX_STRING_LEN];
+int ap_coredumpdir_configured;
+int ap_graceful_shutdown_timeout;
+apr_uint32_t ap_max_mem_free;
+apr_size_t ap_thread_stacksize;
+
+/* Set defaults for config directives implemented here.  This is
+ * called from core's pre-config hook, so MPMs which need to override
+ * one of these should run their pre-config hook after that of core.
+ */
+void mpm_common_pre_config(apr_pool_t *pconf)
+{
+    ap_pid_fname = DEFAULT_PIDLOG;
+    ap_max_requests_per_child = 0; /* unlimited */
+    apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
+    ap_coredumpdir_configured = 0;
+    ap_graceful_shutdown_timeout = 0; /* unlimited */
+    ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
+    ap_thread_stacksize = 0; /* use system default */
+}
+
 /* number of calls to wait_or_timeout between writable probes */
 #ifndef INTERVAL_OF_WRITABLE_PROBES
 #define INTERVAL_OF_WRITABLE_PROBES 10
@@ -108,14 +164,14 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(const char *, mpm_get_name,
 static int wait_or_timeout_counter;
 
 void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret,
-                        apr_pool_t *p)
+                        apr_pool_t *p, server_rec *s)
 {
     apr_status_t rv;
 
     ++wait_or_timeout_counter;
     if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
         wait_or_timeout_counter = 0;
-        ap_run_monitor(p);
+        ap_run_monitor(p, s);
     }
 
     rv = apr_proc_wait_all_procs(ret, exitcode, status, APR_NOWAIT, p);
@@ -128,7 +184,7 @@ void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret,
         return;
     }
 
-    apr_sleep(1000000);
+    apr_sleep(apr_time_from_sec(1));
     ret->pid = -1;
     return;
 }
@@ -193,7 +249,7 @@ AP_DECLARE(gid_t) ap_gname2id(const char *name)
 #ifndef HAVE_INITGROUPS
 int initgroups(const char *name, gid_t basegid)
 {
-#if defined(_OSD_POSIX) || defined(WIN32) || defined(NETWARE)
+#if defined(_OSD_POSIX) || defined(OS2) || defined(WIN32) || defined(NETWARE)
     return 0;
 #else
     gid_t groups[NGROUPS_MAX];
@@ -220,10 +276,9 @@ int initgroups(const char *name, gid_t basegid)
     return setgroups(index, groups);
 #endif
 }
-#endif /* def NEED_INITGROUPS */
+#endif /* def HAVE_INITGROUPS */
 
 /* standard mpm configuration handling */
-const char *ap_pid_fname = NULL;
 
 const char *ap_mpm_set_pidfile(cmd_parms *cmd, void *dummy,
                                const char *arg)
@@ -241,34 +296,6 @@ const char *ap_mpm_set_pidfile(cmd_parms *cmd, void *dummy,
     return NULL;
 }
 
-const char * ap_mpm_set_scoreboard(cmd_parms *cmd, void *dummy,
-                                   const char *arg)
-{
-    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
-    if (err != NULL) {
-        return err;
-    }
-
-    ap_scoreboard_fname = arg;
-    return NULL;
-}
-
-const char *ap_lock_fname = NULL;
-
-const char *ap_mpm_set_lockfile(cmd_parms *cmd, void *dummy,
-                                const char *arg)
-{
-    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
-    if (err != NULL) {
-        return err;
-    }
-
-    ap_lock_fname = arg;
-    return NULL;
-}
-
-int ap_max_requests_per_child = 0;
-
 const char *ap_mpm_set_max_requests(cmd_parms *cmd, void *dummy,
                                     const char *arg)
 {
@@ -277,18 +304,20 @@ const char *ap_mpm_set_max_requests(cmd_parms *cmd, void *dummy,
         return err;
     }
 
+    if (!strcasecmp(cmd->cmd->name, "MaxRequestsPerChild")) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                     "MaxRequestsPerChild is deprecated, use "
+                     "MaxConnectionsPerChild instead.");
+    }
+
     ap_max_requests_per_child = atoi(arg);
 
     return NULL;
 }
 
-char ap_coredump_dir[MAX_STRING_LEN];
-int ap_coredumpdir_configured;
-
 const char *ap_mpm_set_coredumpdir(cmd_parms *cmd, void *dummy,
                                    const char *arg)
 {
-    apr_status_t rv;
     apr_finfo_t finfo;
     const char *fname;
     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
@@ -301,7 +330,7 @@ const char *ap_mpm_set_coredumpdir(cmd_parms *cmd, void *dummy,
         return apr_pstrcat(cmd->pool, "Invalid CoreDumpDirectory path ",
                            arg, NULL);
     }
-    if ((rv = apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool)) != APR_SUCCESS) {
+    if (apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS) {
         return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
                            " does not exist", NULL);
     }
@@ -314,8 +343,6 @@ const char *ap_mpm_set_coredumpdir(cmd_parms *cmd, void *dummy,
     return NULL;
 }
 
-int ap_graceful_shutdown_timeout = 0;
-
 const char * ap_mpm_set_graceful_shutdown(cmd_parms *cmd, void *dummy,
                                           const char *arg)
 {
@@ -327,37 +354,6 @@ const char * ap_mpm_set_graceful_shutdown(cmd_parms *cmd, void *dummy,
     return NULL;
 }
 
-apr_lockmech_e ap_accept_lock_mech = APR_LOCK_DEFAULT;
-
-const char *ap_mpm_set_accept_lock_mech(cmd_parms *cmd,
-                                        void *dummy,
-                                        const char *arg)
-{
-    apr_status_t rv;
-    const char *lockfile;
-    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
-    if (err != NULL) {
-        return err;
-    }
-
-    rv = ap_parse_mutex(arg, cmd->server->process->pool,
-                        &ap_accept_lock_mech, &lockfile);
-
-    if ((rv == APR_ENOTIMPL) || (rv == APR_ENOLOCK)) {
-        return apr_pstrcat(cmd->pool, "Invalid AcceptMutex argument ", arg,
-                           " (" AP_AVAILABLE_MUTEXES_STRING ")", NULL);
-    } else if (rv == APR_BADARG) {
-            return apr_pstrcat(cmd->pool, "Invalid AcceptMutex filepath ",
-                               arg, NULL);
-    }
-
-    if (lockfile && !ap_lock_fname)
-        ap_lock_fname = lockfile;
-    return NULL;
-}
-
-apr_uint32_t ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
-
 const char *ap_mpm_set_max_mem_free(cmd_parms *cmd, void *dummy,
                                     const char *arg)
 {
@@ -377,8 +373,6 @@ const char *ap_mpm_set_max_mem_free(cmd_parms *cmd, void *dummy,
     return NULL;
 }
 
-apr_size_t ap_thread_stacksize = 0; /* use system default */
-
 const char *ap_mpm_set_thread_stacksize(cmd_parms *cmd, void *dummy,
                                         const char *arg)
 {
@@ -409,9 +403,73 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
     return rv;
 }
 
-AP_DECLARE(apr_status_t) ap_mpm_note_child_killed(int childnum)
+/* core's child-status hook
+ * tracks number of remaining children per generation and
+ * runs the end-generation hook when a generation finishes
+ */
+void ap_core_child_status(server_rec *s, pid_t pid,
+                          ap_generation_t gen, int slot,
+                          mpm_child_status status)
 {
-    return ap_run_mpm_note_child_killed(childnum);
+    mpm_gen_info_t *cur;
+    const char *status_msg = "unknown status";
+
+    if (!gen_head_init) { /* where to run this? */
+        gen_head_init = 1;
+        APR_RING_INIT(&geninfo, mpm_gen_info_t, link);
+        APR_RING_INIT(&unused_geninfo, mpm_gen_info_t, link);
+    }
+
+    cur = APR_RING_FIRST(&geninfo);
+    while (cur != APR_RING_SENTINEL(&geninfo, mpm_gen_info_t, link) &&
+           cur->gen != gen) {
+        cur = APR_RING_NEXT(cur, link);
+    }
+
+    switch(status) {
+    case MPM_CHILD_STARTED:
+        status_msg = "started";
+        if (cur == APR_RING_SENTINEL(&geninfo, mpm_gen_info_t, link)) {
+            /* first child for this generation */
+            if (!APR_RING_EMPTY(&unused_geninfo, mpm_gen_info_t, link)) {
+                cur = APR_RING_FIRST(&unused_geninfo);
+                APR_RING_REMOVE(cur, link);
+            }
+            else {
+                cur = apr_pcalloc(s->process->pool, sizeof *cur);
+            }
+            cur->gen = gen;
+            APR_RING_ELEM_INIT(cur, link);
+            APR_RING_INSERT_HEAD(&geninfo, cur, mpm_gen_info_t, link);
+        }
+        ++cur->active;
+        break;
+    case MPM_CHILD_EXITED:
+        status_msg = "exited";
+        if (cur == APR_RING_SENTINEL(&geninfo, mpm_gen_info_t, link)) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                         "no record of generation %d of exiting child %" APR_PID_T_FMT,
+                         gen, pid);
+        }
+        else {
+            --cur->active;
+            if (!cur->active) {
+                ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf,
+                             "end of generation %d", gen);
+                ap_run_end_generation(ap_server_conf, gen);
+                APR_RING_REMOVE(cur, link);
+                APR_RING_INSERT_HEAD(&unused_geninfo, cur, mpm_gen_info_t, link);
+            }
+        }
+        break;
+    case MPM_CHILD_LOST_SLOT:
+        status_msg = "lost slot";
+        /* we don't track by slot, so it doesn't matter */
+        break;
+    }
+    ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, s,
+                 "mpm child %" APR_PID_T_FMT " (gen %d/slot %d) %s",
+                 pid, gen, slot, status_msg);
 }
 
 AP_DECLARE(apr_status_t) ap_mpm_register_timed_callback(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton)
@@ -429,3 +487,24 @@ AP_DECLARE(const char *)ap_show_mpm(void)
 
     return name;
 }
+
+AP_DECLARE(const char *)ap_check_mpm(void)
+{
+    static const char *last_mpm_name = NULL;
+
+    if (!_hooks.link_mpm || _hooks.link_mpm->nelts == 0)
+        return "No MPM loaded.";
+    else if (_hooks.link_mpm->nelts > 1)
+        return "More than one MPM loaded.";
+
+    if (last_mpm_name) {
+        if (strcmp(last_mpm_name, ap_show_mpm())) {
+            return "The MPM cannot be changed during restart.";
+        }
+    }
+    else {
+        last_mpm_name = apr_pstrdup(ap_pglobal, ap_show_mpm());
+    }
+
+    return NULL;
+}