mpm_common.c revision 7184de27ec1d62a83c41cdeac0953ca9fd661e8c
/* 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
*
*
* 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.
*
* specific to multi-process servers, but NOT to Unix. Which is why it
*/
#include "apr.h"
#include "apr_thread_proc.h"
#include "apr_signal.h"
#include "apr_strings.h"
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apr_getopt.h"
#include "apr_optional.h"
#include "apr_allocator.h"
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_main.h"
#include "mpm_common.h"
#include "ap_mpm.h"
#include "ap_listen.h"
#include "util_mutex.h"
#include "scoreboard.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
#include <unistd.h>
#endif
/* we know core's module_index is 0 */
)
#else
)
#endif
(s, gen))
/* hooks with no args are implemented last, after disabling APR hook probes */
#if defined(APR_HOOK_PROBES_ENABLED)
#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 {
int gen; /* which gen? */
int active; /* number of active processes */
static int gen_head_init; /* yuck */
/* variables representing config directives implemented here */
const char *ap_pid_fname;
char ap_coredump_dir[MAX_STRING_LEN];
/* 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.
*/
{
ap_max_requests_per_child = 0; /* unlimited */
ap_graceful_shutdown_timeout = 0; /* 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
#endif
static int wait_or_timeout_counter;
apr_pool_t *p, server_rec *s)
{
ap_run_monitor(p, s);
}
if (APR_STATUS_IS_EINTR(rv)) {
return;
}
if (APR_STATUS_IS_CHILD_DONE(rv)) {
return;
}
return;
}
#if defined(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.
*/
if (status != APR_SUCCESS) {
"apr_socket_opt_set: (TCP_NODELAY)");
}
}
#endif
#ifdef HAVE_GETPWNAM
{
if (name[0] == '#')
exit(1);
}
}
#endif
#ifdef HAVE_GETGRNAM
{
if (name[0] == '#')
exit(1);
}
}
#endif
#ifndef HAVE_INITGROUPS
{
return 0;
#else
struct group *g;
int index = 0;
setgrent();
char **names;
}
}
}
endgrent();
#endif
}
#endif /* def HAVE_INITGROUPS */
/* standard mpm configuration handling */
const char *arg)
{
return err;
}
return "PidFile directive not allowed in <VirtualHost>";
}
ap_pid_fname = arg;
return NULL;
}
const char *arg)
{
return err;
}
"MaxRequestsPerChild is deprecated, use "
"MaxConnectionsPerChild instead.");
}
return NULL;
}
const char *arg)
{
const char *fname;
return err;
}
if (!fname) {
}
" does not exist", NULL);
}
" is not a directory", NULL);
}
return NULL;
}
const char *arg)
{
return err;
}
return NULL;
}
const char *arg)
{
long value;
return err;
}
return NULL;
}
const char *arg)
{
long value;
return err;
}
return NULL;
}
{
rv = APR_EGENERAL;
}
return rv;
}
/* core's child-status hook
* tracks number of remaining children per generation and
* runs the end-generation hook when a generation finishes
*/
{
const char *status_msg = "unknown status";
if (!gen_head_init) { /* where to run this? */
gen_head_init = 1;
}
}
switch(status) {
case MPM_CHILD_STARTED:
status_msg = "started";
/* first child for this generation */
}
else {
}
}
break;
case MPM_CHILD_EXITED:
status_msg = "exited";
"no record of generation %d of exiting child %" APR_PID_T_FMT,
}
else {
"end of generation %d", gen);
}
}
break;
case MPM_CHILD_LOST_SLOT:
status_msg = "lost slot";
/* we don't track by slot, so it doesn't matter */
break;
}
}
AP_DECLARE(apr_status_t) ap_mpm_register_timed_callback(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton)
{
}
AP_DECLARE(const char *)ap_show_mpm(void)
{
const char *name = ap_run_mpm_get_name();
if (!name) {
name = "";
}
return name;
}
AP_DECLARE(const char *)ap_check_mpm(void)
{
static const char *last_mpm_name = NULL;
return "No MPM loaded.";
return "More than one MPM loaded.";
if (last_mpm_name) {
return "The MPM cannot be changed during restart.";
}
}
else {
}
return NULL;
}