Apache HTTPD
mpmt_os2.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/* Multi-process, multi-threaded MPM for OS/2
18 *
19 * Server consists of
20 * - a main, parent process
21 * - a small, static number of child processes
22 *
23 * The parent process's job is to manage the child processes. This involves
24 * spawning children as required to ensure there are always ap_daemons_to_start
25 * processes accepting connections.
26 *
27 * Each child process consists of a pool of worker threads and a
28 * main thread that accepts connections & passes them to the workers via
29 * a work queue. The worker thread pool is dynamic, managed by a maintenance
30 * thread so that the number of idle threads is kept between
31 * min_spare_threads & max_spare_threads.
32 *
33 */
34
35/*
36 Todo list
37 - Enforce MaxRequestWorkers somehow
38*/
39#define INCL_NOPMAPI
40#define INCL_DOS
41#define INCL_DOSERRORS
42
43#include "ap_config.h"
44#include "httpd.h"
45#include "mpm_default.h"
46#include "http_main.h"
47#include "http_log.h"
48#include "http_config.h"
49#include "http_core.h" /* for get_remote_host */
50#include "http_connection.h"
51#include "ap_mpm.h"
52#include "ap_listen.h"
53#include "apr_portable.h"
54#include "mpm_common.h"
55#include "scoreboard.h"
56#include "apr_strings.h"
57#include <os2.h>
58#include <process.h>
59
60/* We don't need many processes,
61 * they're only for redundancy in the event of a crash
62 */
63#define HARD_SERVER_LIMIT 10
64
65/* Limit on the total number of threads per process
66 */
67#ifndef HARD_THREAD_LIMIT
68#define HARD_THREAD_LIMIT 256
69#endif
70
72static apr_pool_t *pconf = NULL; /* Pool for config stuff */
73
74/* Config globals */
75static int one_process = 0;
76static int ap_daemons_to_start = 0;
77static int ap_thread_limit = 0;
80
81/* Keep track of a few interesting statistics */
83
84/* volatile just in case */
85static int volatile shutdown_pending;
86static int volatile restart_pending;
87static int volatile is_graceful = 0;
88ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */
91
92/* An array of these is stored in a shared memory area for passing
93 * sockets from the parent to child processes
94 */
99
100typedef struct {
102 listen_socket_t listeners[1];
104
105static int master_main();
106static void spawn_child(int slot);
108static void set_signals();
109
110
112{
113 char *listener_shm_name;
115 ULONG rc;
116 pconf = _pconf;
118 restart_pending = 0;
119
121 listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getppid());
123 is_parent_process = rc != 0;
124 ap_scoreboard_fname = apr_psprintf(pconf, "/sharemem/httpd/scoreboard.%d", is_parent_process ? getpid() : getppid());
125
126 if (rc == 0) {
127 /* Child process */
129 int num_listeners = 0;
130
131 ap_mpm_accept_mutex = parent_info->accept_mutex;
132
133 /* Set up a default listener if necessary */
134 if (ap_listeners == NULL) {
135 ap_listen_rec *lr = apr_pcalloc(s->process->pool, sizeof(ap_listen_rec));
137 apr_sockaddr_info_get(&lr->bind_addr, "0.0.0.0", APR_UNSPEC,
138 DEFAULT_HTTP_PORT, 0, s->process->pool);
139 apr_socket_create(&lr->sd, lr->bind_addr->family,
140 SOCK_STREAM, 0, s->process->pool);
141 }
142
143 for (lr = ap_listeners; lr; lr = lr->next) {
145 apr_os_sock_put(&lr->sd, &parent_info->listeners[num_listeners].listen_fd, pconf);
148 }
149
151
152 /* Do the work */
154
155 /* Outta here */
156 return DONE;
157 }
158 else {
159 /* Parent process */
160 int rc;
162
165 "no listening sockets available, shutting down");
166 return !OK;
167 }
168
170
171 rc = master_main();
174
175 if (rc != OK) {
178 "caught %s, shutting down",
179 (rc == DONE) ? "SIGTERM" : "error");
180 return rc;
181 }
182 } /* Parent process */
183
184 return OK; /* Restart */
185}
186
187
188
189/* Main processing of the parent process
190 * returns TRUE if restarting
191 */
192static int master_main()
193{
197 char *listener_shm_name;
199 ULONG rc;
200
202 set_signals();
203
206 "no listening sockets available, shutting down");
207 return !OK;
208 }
209
210 /* Allocate a shared memory block for the array of listeners */
211 for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) {
213 }
214
215 listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getpid());
217 sizeof(parent_info_t) + num_listeners * sizeof(listen_socket_t),
219
220 if (rc) {
222 "failure allocating shared memory, shutting down");
223 return !OK;
224 }
225
226 /* Store the listener sockets in the shared memory area for our children to see */
227 for (listener_num = 0, lr = ap_listeners; lr; lr = lr->next, listener_num++) {
228 apr_os_sock_get(&parent_info->listeners[listener_num].listen_fd, lr->sd);
229 }
230
231 /* Create mutex to prevent multiple child processes from detecting
232 * a connection with apr_poll()
233 */
234
236
237 if (rc) {
239 "failure creating accept mutex, shutting down");
240 return !OK;
241 }
242
243 parent_info->accept_mutex = ap_mpm_accept_mutex;
244
245 /* Allocate shared memory for scoreboard */
246 if (ap_scoreboard_image == NULL) {
247 void *sb_mem;
251
252 if (rc) {
254 "unable to allocate shared memory for scoreboard , exiting");
255 return !OK;
256 }
257
259 }
260
263 "%s configured -- resuming normal operations",
266 "Server built: %s", ap_get_server_built());
267 if (one_process) {
270 return DONE;
271 }
272
273 while (!restart_pending && !shutdown_pending) {
276 int active_children = 0;
277
278 /* Count number of active children */
279 for (slot=0; slot < HARD_SERVER_LIMIT; slot++) {
282 }
283
284 /* Spawn children if needed */
286 if (ap_scoreboard_image->parent[slot].pid == 0) {
289 }
290 }
291
293
294 if (rc == 0) {
295 /* A child has terminated, remove its scoreboard entry & terminate if necessary */
297
298 if (slot < HARD_SERVER_LIMIT) {
301
302 if (proc_rc.codeTerminate == TC_EXIT) {
303 /* Child terminated normally, check its exit code and
304 * terminate server if child indicates a fatal error
305 */
306 if (proc_rc.codeResult == APEXIT_CHILDFATAL)
307 break;
308 }
309 }
310 } else if (rc == ERROR_CHILD_NOT_COMPLETE) {
311 /* No child exited, lets sleep for a while.... */
313 }
314 }
315
316 /* Signal children to shut down, either gracefully or immediately */
317 for (slot=0; slot<HARD_SERVER_LIMIT; slot++) {
319 }
320
322 return restart_pending ? OK : DONE;
323}
324
325
326
327static void spawn_child(int slot)
328{
329 PPIB ppib;
330 PTIB ptib;
331 char fail_module[100];
332 char progname[CCHMAXPATH];
334 ULONG rc;
335
338 DosQueryModuleName(ppib->pib_hmte, sizeof(progname), progname);
340 ppib->pib_pchcmd, NULL, &proc_rc, progname);
341
342 if (rc) {
344 "error spawning child, slot %d", slot);
345 }
346
347 if (slot + 1 > ap_max_daemons_limit) {
349 }
350
351 ap_scoreboard_image->parent[slot].pid = proc_rc.codeTerminate;
352}
353
354
355
356/* Signal handling routines */
357
358static void sig_term(int sig)
359{
362}
363
364
365
366static void sig_restart(int sig)
367{
368 if (sig == SIGUSR1) {
369 is_graceful = 1;
370 }
371
372 restart_pending = 1;
373}
374
375
376
377static void set_signals()
378{
379 struct sigaction sa;
380
381 sigemptyset(&sa.sa_mask);
382 sa.sa_flags = 0;
383 sa.sa_handler = sig_term;
384
385 if (sigaction(SIGTERM, &sa, NULL) < 0)
386 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00209) "sigaction(SIGTERM)");
387
388 if (sigaction(SIGINT, &sa, NULL) < 0)
389 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00210) "sigaction(SIGINT)");
390
391 sa.sa_handler = sig_restart;
392
393 if (sigaction(SIGHUP, &sa, NULL) < 0)
394 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00211) "sigaction(SIGHUP)");
395 if (sigaction(SIGUSR1, &sa, NULL) < 0)
396 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00212) "sigaction(SIGUSR1)");
397}
398
399
400
401/* Enquiry functions used get MPM status info */
402
404{
405 *rv = APR_SUCCESS;
406
407 switch (query_code) {
410 break;
411
414 break;
415
418 break;
419
422 break;
423
426 break;
427
429 *result = 0;
430 break;
431
433 *result = 0;
434 break;
435
438 break;
439
442 break;
443
444 default:
445 *rv = APR_ENOTIMPL;
446 break;
447 }
448
449 return OK;
450}
451
452
453
454
455static const char *mpmt_os2_get_name(void)
456{
457 return "mpmt_os2";
458}
459
460
461
462
463/* Configuration handling stuff */
464
480
481
482
484 apr_pool_t *ptemp, server_rec *s)
485{
486 static int restart_num = 0;
487 int startup = 0;
488
489 /* we want this only the first time around */
490 if (restart_num++ == 0) {
491 startup = 1;
492 }
493
494 if (ap_daemons_to_start < 0) {
495 if (startup) {
497 "WARNING: StartServers of %d not allowed, "
498 "increasing to 1.", ap_daemons_to_start);
499 } else {
501 "StartServers of %d not allowed, increasing to 1",
503 }
505 }
506
507 if (ap_min_spare_threads < 1) {
508 if (startup) {
510 "WARNING: MinSpareThreads of %d not allowed, "
511 "increasing to 1 to avoid almost certain server failure. "
512 "Please read the documentation.", ap_min_spare_threads);
513 } else {
515 "MinSpareThreads of %d not allowed, increasing to 1",
517 }
519 }
520
521 return OK;
522}
523
524
525
534
535
536
537static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
538{
539 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
540
541 if (err != NULL) {
542 return err;
543 }
544
546 return NULL;
547}
548
549
550
551static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy,
552 const char *arg)
553{
554 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
555
556 if (err != NULL) {
557 return err;
558 }
559
561 return NULL;
562}
563
564
565
566static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy,
567 const char *arg)
568{
569 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
570
571 if (err != NULL) {
572 return err;
573 }
574
576 return NULL;
577}
578
579
580
581static const char *ignore_cmd(cmd_parms *cmd, void *dummy, const char *arg)
582{
583 return NULL;
584}
585
586
587
588static const command_rec mpmt_os2_cmds[] = {
591 "Number of child processes launched at server startup" ),
593 "Minimum number of idle children, to handle request spikes"),
595 "Maximum number of idle children"),
597 "Not applicable on this platform"),
599 "Not applicable on this platform"),
600AP_INIT_TAKE1("ScoreBoardFile", ignore_cmd, NULL, RSRC_CONF, \
601 "Not applicable on this platform"),
602{ NULL }
603};
604
607 NULL, /* hook to run before apache parses args */
608 NULL, /* create per-directory config structure */
609 NULL, /* merge per-directory config structures */
610 NULL, /* create per-server config structure */
611 NULL, /* merge per-server config structures */
612 mpmt_os2_cmds, /* command apr_table_t */
613 mpmt_os2_hooks, /* register_hooks */
614};
Symbol export macros and hook functions.
Apache Listeners Library.
Apache Multi-Processing Module library.
#define TRUE
Definition abts.h:38
#define FALSE
Definition abts.h:35
APR Portability Routines.
APR Strings library.
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define AP_DECLARE_MODULE(foo)
void ap_hook_check_config(ap_HOOK_check_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:96
void ap_hook_pre_config(ap_HOOK_pre_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:91
const char * ap_get_server_built(void)
Definition buildmark.c:26
const char * ap_get_server_description(void)
Definition core.c:3587
#define OK
Definition httpd.h:456
#define DEFAULT_HTTP_PORT
Definition httpd.h:278
#define DONE
Definition httpd.h:458
#define APEXIT_CHILDFATAL
Definition httpd.h:341
int ap_exists_config_define(const char *name)
Definition core.c:2896
#define LISTEN_COMMANDS
Definition ap_listen.h:146
void ap_listen_pre_config(void)
Definition listen.c:804
ap_listen_rec * ap_listeners
Definition listen.c:42
int ap_setup_listeners(server_rec *s)
Definition listen.c:610
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_NOTICE
Definition http_log.h:69
#define APLOG_STARTUP
Definition http_log.h:105
#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
void ap_remove_pid(apr_pool_t *p, const char *fname)
Definition log.c:1611
#define APLOG_ALERT
Definition http_log.h:65
void ap_log_pid(apr_pool_t *p, const char *fname)
Definition log.c:1630
server_rec * ap_server_conf
Definition mpmt_os2.c:71
void ap_hook_mpm(ap_HOOK_mpm_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mpm_common.c:97
void * dummy
Definition http_vhost.h:62
void const char * arg
Definition http_vhost.h:63
#define DEFAULT_START_DAEMON
Definition mpm_default.h:34
#define DEFAULT_MAX_SPARE_THREAD
Definition mpm_default.h:40
#define DEFAULT_MIN_SPARE_THREAD
Definition mpm_default.h:46
#define SCOREBOARD_MAINTENANCE_INTERVAL
Definition mpm_default.h:53
const char * ap_pid_fname
Definition mpm_common.c:150
int ap_sys_privileges_handlers(int inc)
Definition core.c:5062
int ap_max_requests_per_child
Definition mpm_common.c:151
void ap_hook_mpm_get_name(ap_HOOK_mpm_get_name_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mpm_common.c:136
void ap_hook_mpm_query(ap_HOOK_mpm_query_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mpm_common.c:100
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
apr_redis_t * rc
Definition apr_redis.h:173
#define RSRC_CONF
#define MPM20_MODULE_STUFF
#define GLOBAL_ONLY
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
apr_size_t size
#define APR_FROM_OS_ERROR(e)
Definition apr_errno.h:1214
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_array_header_t ** result
apr_sockaddr_t * sa
#define APR_UNSPEC
@ APR_LOCAL
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
int apr_os_sock_t
const char * s
Definition apr_strings.h:95
apr_int32_t apr_int32_t apr_int32_t err
int sig
apr_cmdtype_e cmd
const char * progname
#define AP_MPMQ_IS_FORKED
Definition ap_mpm.h:154
#define AP_MPMQ_MAX_DAEMON_USED
Definition ap_mpm.h:150
#define AP_MPMQ_MAX_SPARE_DAEMONS
Definition ap_mpm.h:166
#define AP_MPMQ_HARD_LIMIT_THREADS
Definition ap_mpm.h:158
#define AP_MPMQ_IS_THREADED
Definition ap_mpm.h:152
#define AP_MPMQ_MAX_REQUESTS_DAEMON
Definition ap_mpm.h:170
#define AP_MPMQ_GENERATION
Definition ap_mpm.h:178
#define AP_MPMQ_HARD_LIMIT_DAEMONS
Definition ap_mpm.h:156
#define AP_MPMQ_MIN_SPARE_DAEMONS
Definition ap_mpm.h:162
#define AP_MPMQ_DYNAMIC
Definition ap_mpm.h:131
#define AP_MPMQ_NOT_SUPPORTED
Definition ap_mpm.h:125
Apache Configuration.
Apache connection library.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
Multi-Processing Modules functions.
static int one_process
Definition mpmt_os2.c:75
ap_generation_t volatile ap_my_generation
Definition mpmt_os2.c:88
static void sig_term(int sig)
Definition mpmt_os2.c:358
static apr_status_t mpmt_os2_query(int query_code, int *result, apr_status_t *rv)
Definition mpmt_os2.c:403
#define HARD_SERVER_LIMIT
Definition mpmt_os2.c:63
int ap_max_spare_threads
Definition mpmt_os2.c:79
static void mpmt_os2_hooks(apr_pool_t *p)
Definition mpmt_os2.c:526
static const char * ignore_cmd(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpmt_os2.c:581
static int volatile restart_pending
Definition mpmt_os2.c:86
int ap_min_spare_threads
Definition mpmt_os2.c:78
static apr_pool_t * pconf
Definition mpmt_os2.c:72
static int ap_thread_limit
Definition mpmt_os2.c:77
static const char * set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpmt_os2.c:551
int ap_max_daemons_limit
Definition mpmt_os2.c:82
static int mpmt_os2_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
Definition mpmt_os2.c:111
static const char * set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpmt_os2.c:566
static void spawn_child(int slot)
Definition mpmt_os2.c:327
HMTX ap_mpm_accept_mutex
Definition mpmt_os2.c:90
void ap_mpm_child_main(apr_pool_t *pconf)
static int master_main()
Definition mpmt_os2.c:192
static const char * set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
Definition mpmt_os2.c:537
static int volatile is_graceful
Definition mpmt_os2.c:87
static const command_rec mpmt_os2_cmds[]
Definition mpmt_os2.c:588
static int is_parent_process
Definition mpmt_os2.c:89
#define HARD_THREAD_LIMIT
Definition mpmt_os2.c:68
static int mpmt_os2_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
Definition mpmt_os2.c:465
static int ap_daemons_to_start
Definition mpmt_os2.c:76
static void set_signals()
Definition mpmt_os2.c:377
static int volatile shutdown_pending
Definition mpmt_os2.c:85
static const char * mpmt_os2_get_name(void)
Definition mpmt_os2.c:455
static int mpmt_os2_check_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
Definition mpmt_os2.c:483
static void sig_restart(int sig)
Definition mpmt_os2.c:366
Apache scoreboard library.
int ap_generation_t
Definition scoreboard.h:78
scoreboard * ap_scoreboard_image
Definition scoreboard.c:44
const char * ap_scoreboard_fname
Definition scoreboard.c:45
void ap_init_scoreboard(void *shared_score)
Definition scoreboard.c:150
int ap_extended_status
Definition scoreboard.c:61
int ap_calc_scoreboard_size(void)
Definition scoreboard.c:138
char * name
Apache's listeners record.
Definition ap_listen.h:47
ap_listen_rec * next
Definition ap_listen.h:51
ap_generation_t running_generation
Definition scoreboard.h:126
apr_time_t restart_time
Definition scoreboard.h:129
apr_os_sock_t listen_fd
Definition mpmt_os2.c:97
HMTX accept_mutex
Definition mpmt_os2.c:101
ap_generation_t generation
Definition scoreboard.h:139
process_score * parent
Definition scoreboard.h:162
global_score * global
Definition scoreboard.h:161
A structure to store information for each virtual server.
Definition httpd.h:1322
apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock)
Definition sockets.c:506
apr_status_t apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, apr_pool_t *cont)
Definition sockets.c:550
apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, int protocol, apr_pool_t *cont)
Definition sockets.c:116
Worker MPM defaults.