/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
/* The purpose of this file is to store the code that MOST mpm's will need * this does not mean a function only goes into this file if every MPM needs * it. It means that if a function is needed by more than one MPM, and * future maintenance would be served by making the code common, then the * function belongs here. * * This is going in src/main because it is not platform specific, it is * specific to multi-process servers, but NOT to Unix. Which is why it * does not belong in src/os/unix
*/
/* hooks with no args are implemented last, after disabling APR hook probes */ #ifdefined(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(constchar *, mpm_get_name,
(void),
(), NULL)
typedefstruct mpm_gen_info_t {
APR_RING_ENTRY(mpm_gen_info_t) link; int gen; /* which gen? */ int active; /* number of active processes */ int done; /* gen finished? (whether or not active processes) */
} mpm_gen_info_t;
/* variables representing config directives implemented here */
AP_DECLARE_DATA constchar *ap_pid_fname;
AP_DECLARE_DATA int ap_max_requests_per_child;
AP_DECLARE_DATA char ap_coredump_dir[MAX_STRING_LEN];
AP_DECLARE_DATA int ap_coredumpdir_configured;
AP_DECLARE_DATA int ap_graceful_shutdown_timeout;
AP_DECLARE_DATA apr_uint32_t ap_max_mem_free;
AP_DECLARE_DATA apr_size_t ap_thread_stacksize;
#define ALLOCATOR_MAX_FREE_DEFAULT (2048*1024)
/* 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 = ALLOCATOR_MAX_FREE_DEFAULT;
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 #endif staticint wait_or_timeout_counter;
if (APR_STATUS_IS_EINTR(rv)) {
ret->pid = -1; return;
}
if (APR_STATUS_IS_CHILD_DONE(rv)) { return;
}
apr_sleep(apr_time_from_sec(1));
ret->pid = -1;
}
#ifdefined(TCP_NODELAY) void ap_sock_disable_nagle(apr_socket_t *s)
{ /* The Nagle algorithm says that we should delay sending partial * packets in hopes of getting more data. We don't want to do * this; we are not telnet. There are bad interactions between * persistent connections and Nagle's algorithm that have very severe * performance penalties. (Failing to disable Nagle is not much of a * problem with simple HTTP.) * * In spite of these problems, failure here is not a shooting offense.
*/
apr_status_t status = apr_socket_opt_set(s, APR_TCP_NODELAY, 1);
if (!(ent = getpwnam(name))) {
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00543) "%s: bad user name %s", ap_server_argv0, name); exit(1);
}
return (ent->pw_uid);
} #endif
#ifdef HAVE_GETGRNAM
AP_DECLARE(gid_t) ap_gname2id(constchar *name)
{ struct group *ent;
if (name[0] == '#') return (atoi(&name[1]));
if (!(ent = getgrnam(name))) {
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00544) "%s: bad group name %s", ap_server_argv0, name); exit(1);
}
return (ent->gr_gid);
} #endif
#ifndef HAVE_INITGROUPS int initgroups(constchar *name, gid_t basegid)
{ #ifdefined(_OSD_POSIX) || defined(OS2) || defined(WIN32) || defined(NETWARE) return 0; #else
gid_t groups[NGROUPS_MAX]; struct group *g; int index = 0;
setgrent();
groups[index++] = basegid;
while (index < NGROUPS_MAX && ((g = getgrent()) != NULL)) { if (g->gr_gid != basegid) { char **names;
for (names = g->gr_mem; *names != NULL; ++names) { if (!strcmp(*names, name))
groups[index++] = g->gr_gid;
}
}
}
apr_status_t ap_mpm_end_gen_helper(void *unused) /* cleanup on pconf */
{ int gen = ap_config_generation - 1; /* differs from MPM generation */
mpm_gen_info_t *cur;
if (geninfo == NULL) { /* initial pconf teardown, MPM hasn't run */ return APR_SUCCESS;
}
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);
}
if (cur == APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link)) { /* last child of generation already exited */
ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf, "no record of generation %d", gen);
} else {
cur->done = 1; if (cur->active == 0) {
end_gen(cur);
}
}
return APR_SUCCESS;
}
/* core's child-status hook * tracks number of remaining children per generation and * runs the end-generation hook when the last child of * a generation exits
*/ void ap_core_child_status(server_rec *s, pid_t pid,
ap_generation_t gen, int slot,
mpm_child_status status)
{
mpm_gen_info_t *cur; constchar *status_msg = "unknown status";
if (!gen_head_init) { /* where to run this? */
gen_head_init = 1;
geninfo = apr_pcalloc(s->process->pool, sizeof *geninfo);
unused_geninfo = apr_pcalloc(s->process->pool, sizeof *unused_geninfo);
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);
cur->active = cur->done = 0;
} 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);
}
ap_random_parent_after_fork();
++cur->active; break; case MPM_CHILD_EXITED:
ap_update_global_status();
status_msg = "exited"; if (cur == APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link)) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00546) "no record of generation %d of exiting child %" APR_PID_T_FMT,
gen, pid);
} else {
--cur->active; if (!cur->active && cur->done) { /* no children, server has stopped/restarted */
end_gen(cur);
}
} 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);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.