Apache HTTPD
mpm_common.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* The purpose of this file is to store the code that MOST mpm's will need
18 * this does not mean a function only goes into this file if every MPM needs
19 * it. It means that if a function is needed by more than one MPM, and
20 * future maintenance would be served by making the code common, then the
21 * function belongs here.
22 *
23 * This is going in src/main because it is not platform specific, it is
24 * specific to multi-process servers, but NOT to Unix. Which is why it
25 * does not belong in src/os/unix
26 */
27
28#include "apr.h"
29#include "apr_thread_proc.h"
30#include "apr_signal.h"
31#include "apr_strings.h"
32#define APR_WANT_STRFUNC
33#include "apr_want.h"
34#include "apr_getopt.h"
35#include "apr_optional.h"
36#include "apr_allocator.h"
37
38#include "httpd.h"
39#include "http_config.h"
40#include "http_core.h"
41#include "http_log.h"
42#include "http_main.h"
43#include "mpm_common.h"
44#include "mod_core.h"
45#include "ap_mpm.h"
46#include "ap_listen.h"
47#include "util_mutex.h"
48
49#include "scoreboard.h"
50
51#ifdef HAVE_PWD_H
52#include <pwd.h>
53#endif
54#ifdef HAVE_GRP_H
55#include <grp.h>
56#endif
57#if APR_HAVE_UNISTD_H
58#include <unistd.h>
59#endif
60
61/* we know core's module_index is 0 */
62#undef APLOG_MODULE_INDEX
63#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
64
65#define DEFAULT_HOOK_LINKS \
66 APR_HOOK_LINK(monitor) \
67 APR_HOOK_LINK(drop_privileges) \
68 APR_HOOK_LINK(mpm) \
69 APR_HOOK_LINK(mpm_query) \
70 APR_HOOK_LINK(mpm_register_timed_callback) \
71 APR_HOOK_LINK(mpm_get_name) \
72 APR_HOOK_LINK(end_generation) \
73 APR_HOOK_LINK(child_status) \
74 APR_HOOK_LINK(suspend_connection) \
75 APR_HOOK_LINK(resume_connection) \
76 APR_HOOK_LINK(child_stopping)
77
78#if AP_ENABLE_EXCEPTION_HOOK
82)
85#else
89#endif
90AP_IMPLEMENT_HOOK_RUN_ALL(int, monitor,
99 (int query_code, int *result, apr_status_t *_rv),
106 (s, gen))
109 (s,pid,gen,slot,status))
111 (conn_rec *c, request_rec *r),
112 (c, r))
114 (conn_rec *c, request_rec *r),
115 (c, r))
117 (apr_pool_t *pchild, int graceful),
119
120/* hooks with no args are implemented last, after disabling APR hook probes */
121#if defined(APR_HOOK_PROBES_ENABLED)
122#undef APR_HOOK_PROBES_ENABLED
123#undef APR_HOOK_PROBE_ENTRY
124#define APR_HOOK_PROBE_ENTRY(ud,ns,name,args)
125#undef APR_HOOK_PROBE_RETURN
126#define APR_HOOK_PROBE_RETURN(ud,ns,name,rv,args)
127#undef APR_HOOK_PROBE_INVOKE
128#define APR_HOOK_PROBE_INVOKE(ud,ns,name,src,args)
129#undef APR_HOOK_PROBE_COMPLETE
130#define APR_HOOK_PROBE_COMPLETE(ud,ns,name,src,rv,args)
131#undef APR_HOOK_INT_DCL_UD
132#define APR_HOOK_INT_DCL_UD
133#endif
135 (void),
136 (), NULL)
137
140 int gen; /* which gen? */
141 int active; /* number of active processes */
142 int done; /* gen finished? (whether or not active processes) */
144
147static int gen_head_init; /* yuck */
148
149/* variables representing config directives implemented here */
157
158#define ALLOCATOR_MAX_FREE_DEFAULT (2048*1024)
159
160/* Set defaults for config directives implemented here. This is
161 * called from core's pre-config hook, so MPMs which need to override
162 * one of these should run their pre-config hook after that of core.
163 */
174
175/* number of calls to wait_or_timeout between writable probes */
176#ifndef INTERVAL_OF_WRITABLE_PROBES
177#define INTERVAL_OF_WRITABLE_PROBES 10
178#endif
180
183 server_rec *s)
184{
185 apr_status_t rv;
186
191 }
192
195
196 if (APR_STATUS_IS_EINTR(rv)) {
197 ret->pid = -1;
198 return;
199 }
200
201 if (APR_STATUS_IS_CHILD_DONE(rv)) {
202 return;
203 }
204
206 ret->pid = -1;
207}
208
209#if defined(TCP_NODELAY)
211{
212 /* The Nagle algorithm says that we should delay sending partial
213 * packets in hopes of getting more data. We don't want to do
214 * this; we are not telnet. There are bad interactions between
215 * persistent connections and Nagle's algorithm that have very severe
216 * performance penalties. (Failing to disable Nagle is not much of a
217 * problem with simple HTTP.)
218 *
219 * In spite of these problems, failure here is not a shooting offense.
220 */
222
223 if (status != APR_SUCCESS) {
225 "apr_socket_opt_set: (TCP_NODELAY)");
226 }
227}
228#endif
229
230#ifdef HAVE_GETPWNAM
231AP_DECLARE(uid_t) ap_uname2id(const char *name)
232{
233 struct passwd *ent;
234
235 if (name[0] == '#')
236 return (atoi(&name[1]));
237
238 if (!(ent = getpwnam(name))) {
240 "%s: bad user name %s", ap_server_argv0, name);
241 exit(1);
242 }
243
244 return (ent->pw_uid);
245}
246#endif
247
248#ifdef HAVE_GETGRNAM
249AP_DECLARE(gid_t) ap_gname2id(const char *name)
250{
251 struct group *ent;
252
253 if (name[0] == '#')
254 return (atoi(&name[1]));
255
256 if (!(ent = getgrnam(name))) {
258 "%s: bad group name %s", ap_server_argv0, name);
259 exit(1);
260 }
261
262 return (ent->gr_gid);
263}
264#endif
265
266#ifndef HAVE_INITGROUPS
267int initgroups(const char *name, gid_t basegid)
268{
269#if defined(_OSD_POSIX) || defined(OS2) || defined(WIN32) || defined(NETWARE)
270 return 0;
271#else
273 struct group *g;
274 int index = 0;
275
276 setgrent();
277
278 groups[index++] = basegid;
279
280 while (index < NGROUPS_MAX && ((g = getgrent()) != NULL)) {
281 if (g->gr_gid != basegid) {
282 char **names;
283
284 for (names = g->gr_mem; *names != NULL; ++names) {
285 if (!strcmp(*names, name))
286 groups[index++] = g->gr_gid;
287 }
288 }
289 }
290
291 endgrent();
292
293 return setgroups(index, groups);
294#endif
295}
296#endif /* def HAVE_INITGROUPS */
297
298/* standard mpm configuration handling */
299
301 const char *arg)
302{
303 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
304 if (err != NULL) {
305 return err;
306 }
307
308 if (cmd->server->is_virtual) {
309 return "PidFile directive not allowed in <VirtualHost>";
310 }
311
313 return NULL;
314}
315
321
323 const char *arg)
324{
325 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
326 if (err != NULL) {
327 return err;
328 }
329
330 if (!strcasecmp(cmd->cmd->name, "MaxRequestsPerChild")) {
332 "MaxRequestsPerChild is deprecated, use "
333 "MaxConnectionsPerChild instead.");
334 }
335
337
338 return NULL;
339}
340
342 const char *arg)
343{
344 apr_finfo_t finfo;
345 const char *fname;
346 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
347 if (err != NULL) {
348 return err;
349 }
350
351 fname = ap_server_root_relative(cmd->temp_pool, arg);
352 if (!fname) {
353 return apr_pstrcat(cmd->pool, "Invalid CoreDumpDirectory path ",
354 arg, NULL);
355 }
356 if (apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS) {
357 return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
358 " does not exist", NULL);
359 }
360 if (finfo.filetype != APR_DIR) {
361 return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
362 " is not a directory", NULL);
363 }
366 return NULL;
367}
368
370 void *dummy,
371 const char *arg)
372{
373 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
374 if (err != NULL) {
375 return err;
376 }
378 return NULL;
379}
380
382 const char *arg)
383{
384 long value;
385 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
386 if (err != NULL) {
387 return err;
388 }
389
390 errno = 0;
391 value = strtol(arg, NULL, 10);
392 if (value < 0 || errno == ERANGE)
393 return apr_pstrcat(cmd->pool, "Invalid MaxMemFree value: ",
394 arg, NULL);
395
397
398 return NULL;
399}
400
402 const char *arg)
403{
404 long value;
405 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
406 if (err != NULL) {
407 return err;
408 }
409
410 errno = 0;
411 value = strtol(arg, NULL, 10);
412 if (value < 0 || errno == ERANGE)
413 return apr_pstrcat(cmd->pool, "Invalid ThreadStackSize value: ",
414 arg, NULL);
415
417
418 return NULL;
419}
420
422{
423 apr_status_t rv;
424
426 rv = APR_EGENERAL;
427 }
428
429 return rv;
430}
431
433{
435 "end of generation %d", gi->gen);
437 APR_RING_REMOVE(gi, link);
439}
440
441apr_status_t ap_mpm_end_gen_helper(void *unused) /* cleanup on pconf */
442{
443 int gen = ap_config_generation - 1; /* differs from MPM generation */
445
446 if (geninfo == NULL) {
447 /* initial pconf teardown, MPM hasn't run */
448 return APR_SUCCESS;
449 }
450
452 while (cur != APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link) &&
453 cur->gen != gen) {
454 cur = APR_RING_NEXT(cur, link);
455 }
456
458 /* last child of generation already exited */
460 "no record of generation %d", gen);
461 }
462 else {
463 cur->done = 1;
464 if (cur->active == 0) {
465 end_gen(cur);
466 }
467 }
468
469 return APR_SUCCESS;
470}
471
472/* core's child-status hook
473 * tracks number of remaining children per generation and
474 * runs the end-generation hook when the last child of
475 * a generation exits
476 */
478 ap_generation_t gen, int slot,
480{
482 const char *status_msg = "unknown status";
483
484 if (!gen_head_init) { /* where to run this? */
485 gen_head_init = 1;
486 geninfo = apr_pcalloc(s->process->pool, sizeof *geninfo);
487 unused_geninfo = apr_pcalloc(s->process->pool, sizeof *unused_geninfo);
490 }
491
493 while (cur != APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link) &&
494 cur->gen != gen) {
495 cur = APR_RING_NEXT(cur, link);
496 }
497
498 switch(status) {
500 status_msg = "started";
502 /* first child for this generation */
505 APR_RING_REMOVE(cur, link);
506 cur->active = cur->done = 0;
507 }
508 else {
509 cur = apr_pcalloc(s->process->pool, sizeof *cur);
510 }
511 cur->gen = gen;
512 APR_RING_ELEM_INIT(cur, link);
514 }
516 ++cur->active;
517 break;
518 case MPM_CHILD_EXITED:
520 status_msg = "exited";
523 "no record of generation %d of exiting child %" APR_PID_T_FMT,
524 gen, pid);
525 }
526 else {
527 --cur->active;
528 if (!cur->active && cur->done) { /* no children, server has stopped/restarted */
529 end_gen(cur);
530 }
531 }
532 break;
534 status_msg = "lost slot";
535 /* we don't track by slot, so it doesn't matter */
536 break;
537 }
539 "mpm child %" APR_PID_T_FMT " (gen %d/slot %d) %s",
540 pid, gen, slot, status_msg);
541}
542
547
548AP_DECLARE(const char *)ap_show_mpm(void)
549{
550 const char *name = ap_run_mpm_get_name();
551
552 if (!name) {
553 name = "";
554 }
555
556 return name;
557}
558
559AP_DECLARE(const char *)ap_check_mpm(void)
560{
561 static const char *last_mpm_name = NULL;
562
563 if (!_hooks.link_mpm || _hooks.link_mpm->nelts == 0)
564 return "No MPM loaded.";
565 else if (_hooks.link_mpm->nelts > 1)
566 return "More than one MPM loaded.";
567
568 if (last_mpm_name) {
570 return "The MPM cannot be changed during restart.";
571 }
572 }
573 else {
575 }
576
577 return NULL;
578}
#define AP_DECLARE_DATA
Definition ap_config.h:89
#define DEFAULT_PIDLOG
Definition ap_config.h:144
#define AP_DECLARE(type)
Definition ap_config.h:67
#define AP_IMPLEMENT_HOOK_VOID(name, args_decl, args_use)
Definition ap_hooks.h:94
#define AP_IMPLEMENT_HOOK_RUN_ALL(ret, name, args_decl, args_use, ok, decline)
Definition ap_hooks.h:117
#define AP_IMPLEMENT_HOOK_RUN_FIRST(ret, name, args_decl, args_use, decline)
Definition ap_hooks.h:137
Apache Listeners Library.
Apache Multi-Processing Module library.
APR Internal Memory Allocation.
APR Command Arguments (getopt)
APR-UTIL registration of functions exported by modules.
APR Signal Handling.
APR Strings library.
APR Thread and Process Library.
APR Standard Headers Support.
static apr_pool_t * pconf
Definition event.c:441
char * ap_server_root_relative(apr_pool_t *p, const char *fname)
Definition config.c:1594
request_rec * r
const char * ap_show_mpm(void)
Definition mpm_common.c:548
#define MAX_STRING_LEN
Definition httpd.h:300
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_STARTUP
Definition http_log.h:105
#define APLOG_TRACE4
Definition http_log.h:75
#define APLOG_INFO
Definition http_log.h:70
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_WARNING
Definition http_log.h:68
const char * ap_server_argv0
Definition config.c:60
const char * ap_server_root
Definition config.c:61
apr_pool_t * ap_pglobal
Definition config.c:63
int ap_config_generation
Definition core.c:151
server_rec * ap_server_conf
Definition config.c:62
mpm_child_status
Definition ap_mpm.h:205
void ap_run_end_generation(server_rec *s, ap_generation_t gen)
Definition mpm_common.c:106
apr_status_t ap_mpm_register_timed_callback(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton)
Definition mpm_common.c:543
void() ap_mpm_callback_fn_t(void *baton)
Definition ap_mpm.h:198
@ MPM_CHILD_EXITED
Definition ap_mpm.h:207
@ MPM_CHILD_STARTED
Definition ap_mpm.h:206
@ MPM_CHILD_LOST_SLOT
Definition ap_mpm.h:208
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
void * dummy
Definition http_vhost.h:62
void const char * arg
Definition http_vhost.h:63
int ap_run_monitor(apr_pool_t *p, server_rec *s)
Definition mpm_common.c:91
void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret, apr_pool_t *p, server_rec *s)
Definition mpm_common.c:181
const char * ap_pid_fname
Definition mpm_common.c:150
char ap_coredump_dir[8192]
Definition mpm_common.c:152
void mpm_common_pre_config(apr_pool_t *pconf)
Definition mpm_common.c:164
const char * ap_check_mpm(void)
Definition mpm_common.c:559
int ap_max_requests_per_child
Definition mpm_common.c:151
const char * ap_mpm_set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpm_common.c:300
const char * ap_mpm_set_graceful_shutdown(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpm_common.c:369
int ap_coredumpdir_configured
Definition mpm_common.c:153
const char * ap_mpm_set_coredumpdir(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpm_common.c:341
int ap_graceful_shutdown_timeout
Definition mpm_common.c:154
#define ap_sock_disable_nagle(s)
Definition mpm_common.h:200
int initgroups(const char *name, gid_t basegid)
Definition mpm_common.c:267
apr_status_t ap_run_mpm_register_timed_callback(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton)
Definition mpm_common.c:103
apr_size_t ap_thread_stacksize
Definition mpm_common.c:156
void ap_mpm_dump_pidfile(apr_pool_t *p, apr_file_t *out)
Definition mpm_common.c:316
void ap_core_child_status(server_rec *s, pid_t pid, ap_generation_t gen, int slot, mpm_child_status status)
Definition mpm_common.c:477
apr_uint32_t ap_max_mem_free
Definition mpm_common.c:155
const char * ap_mpm_set_max_requests(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpm_common.c:322
int ap_run_mpm_query(int query_code, int *result, apr_status_t *_rv)
Definition mpm_common.c:100
apr_status_t ap_mpm_end_gen_helper(void *unused)
Definition mpm_common.c:441
const char * ap_run_mpm_get_name(void)
Definition mpm_common.c:136
const char * ap_mpm_set_thread_stacksize(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpm_common.c:401
const char * ap_mpm_set_max_mem_free(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpm_common.c:381
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_STATUS_IS_CHILD_DONE(s)
Definition apr_errno.h:520
#define APR_STATUS_IS_EINTR(s)
Definition apr_errno.h:1281
#define APR_HOOK_LINK(name)
Definition apr_hooks.h:139
#define APR_HOOK_STRUCT(members)
Definition apr_hooks.h:135
void ap_random_parent_after_fork(void)
Definition core.c:5420
#define GLOBAL_ONLY
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
apr_size_t size
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
@ APR_DIR
const char * fname
#define APR_FINFO_TYPE
apr_array_header_t ** result
int strcasecmp(const char *a, const char *b)
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_interval_time_t t
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
#define APR_RING_ENTRY(elem)
Definition apr_ring.h:70
#define APR_RING_INIT(hp, elem, link)
Definition apr_ring.h:192
#define APR_RING_HEAD(head, elem)
Definition apr_ring.h:91
#define APR_RING_SENTINEL(hp, elem, link)
Definition apr_ring.h:159
#define APR_RING_EMPTY(hp, elem, link)
Definition apr_ring.h:204
#define APR_RING_REMOVE(ep, link)
Definition apr_ring.h:381
#define APR_RING_FIRST(hp)
Definition apr_ring.h:166
#define APR_RING_INSERT_HEAD(hp, nep, elem, link)
Definition apr_ring.h:317
#define APR_RING_NEXT(ep, link)
Definition apr_ring.h:177
#define APR_RING_ELEM_INIT(ep, link)
Definition apr_ring.h:212
#define APR_TCP_NODELAY
const char * s
Definition apr_strings.h:95
apr_int32_t apr_int32_t apr_int32_t err
apr_cmdtype_e cmd
apr_exit_why_e
int * exitcode
int int status
@ APR_NOWAIT
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_from_sec(sec)
Definition apr_time.h:78
apr_status_t ap_mpm_query(int query_code, int *result)
Definition mpm_common.c:421
static apr_pool_t * pchild
Definition h2_mplx.c:74
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
mod_core private header file
static apr_file_t * out
Definition mod_info.c:85
return NULL
Definition mod_so.c:359
static int gen_head_init
Definition mpm_common.c:147
#define ALLOCATOR_MAX_FREE_DEFAULT
Definition mpm_common.c:158
static struct @47 _hooks
#define DEFAULT_HOOK_LINKS
Definition mpm_common.c:65
static void end_gen(mpm_gen_info_t *gi)
Definition mpm_common.c:432
static struct mpm_gen_info_head_t * unused_geninfo
Definition mpm_common.c:146
static struct mpm_gen_info_head_t * geninfo
Definition mpm_common.c:146
#define INTERVAL_OF_WRITABLE_PROBES
Definition mpm_common.c:177
static int wait_or_timeout_counter
Definition mpm_common.c:179
Multi-Processing Modules functions.
Apache scoreboard library.
int ap_generation_t
Definition scoreboard.h:78
int ap_update_global_status(void)
Definition scoreboard.c:656
char * name
apr_filetype_e filetype
apr_pool_t * pool
Structure to store things which are per connection.
Definition httpd.h:1152
struct mpm_gen_info_t::@48 link
A structure that represents the current request.
Definition httpd.h:845
A structure to store information for each virtual server.
Definition httpd.h:1322
apr_status_t apr_socket_opt_set(apr_socket_t *sock, apr_int32_t opt, apr_int32_t on)
Definition sockopt.c:113
Apache Mutex support library.