mpmt_os2.c revision 1ce78cf71b5baaf2c1ab48e818cb1f2397df5010
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder/* Licensed to the Apache Software Foundation (ASF) under one or more
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * contributor license agreements. See the NOTICE file distributed with
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * this work for additional information regarding copyright ownership.
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * The ASF licenses this file to You under the Apache License, Version 2.0
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * (the "License"); you may not use this file except in compliance with
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * the License. You may obtain a copy of the License at
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * http://www.apache.org/licenses/LICENSE-2.0
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * Unless required by applicable law or agreed to in writing, software
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * distributed under the License is distributed on an "AS IS" BASIS,
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * See the License for the specific language governing permissions and
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * limitations under the License.
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder/* Multi-process, multi-threaded MPM for OS/2
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder * Server consists of
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * - a main, parent process
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * - a small, static number of child processes
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * The parent process's job is to manage the child processes. This involves
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder * spawning children as required to ensure there are always ap_daemons_to_start
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder * processes accepting connections.
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * Each child process consists of a a pool of worker threads and a
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder * main thread that accepts connections & passes them to the workers via
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder * a work queue. The worker thread pool is dynamic, managed by a maintanence
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder * thread so that the number of idle threads is kept between
0c92a39a4adf3c1cbe173e3b16c65c159a1ce612Christian Maeder * min_spare_threads & max_spare_threads.
0c92a39a4adf3c1cbe173e3b16c65c159a1ce612Christian Maeder - Enforce MaxClients somehow
0c92a39a4adf3c1cbe173e3b16c65c159a1ce612Christian Maeder#include "http_core.h" /* for get_remote_host */
d4aed7a2eea6b546c0d9520d85038addb7beb12fChristian Maeder/* We don't need many processes,
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * they're only for redundancy in the event of a crash
bb2c1beb7ab66a49627a2a34df80864a3c65cc83Christian Maeder/* Limit on the total number of threads per process
bb2c1beb7ab66a49627a2a34df80864a3c65cc83Christian Maederstatic apr_pool_t *pconf = NULL; /* Pool for config stuff */
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder/* Config globals */
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder/* Keep track of a few interesting statistics */
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder/* volatile just in case */
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maederstatic int volatile shutdown_pending;
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maederstatic int volatile restart_pending;
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maederstatic int volatile is_graceful = 0;
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maederap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder/* An array of these is stored in a shared memory area for passing
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder * sockets from the parent to child processes
e7b0b439ffae08514ac1afc62186d9a87ec6bd59Christian Maedertypedef struct {
bb2c1beb7ab66a49627a2a34df80864a3c65cc83Christian Maedertypedef struct {
d4aed7a2eea6b546c0d9520d85038addb7beb12fChristian Maederint ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s )
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getppid());
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder rc = DosGetNamedSharedMem((PPVOID)&parent_info, listener_shm_name, PAG_READ);
e7b0b439ffae08514ac1afc62186d9a87ec6bd59Christian Maeder ap_scoreboard_fname = apr_psprintf(pconf, "/sharemem/httpd/scoreboard.%d", is_parent_process ? getpid() : getppid());
bb2c1beb7ab66a49627a2a34df80864a3c65cc83Christian Maeder /* Child process */
bb2c1beb7ab66a49627a2a34df80864a3c65cc83Christian Maeder ap_mpm_accept_mutex = parent_info->accept_mutex;
bb2c1beb7ab66a49627a2a34df80864a3c65cc83Christian Maeder /* Set up a default listener if necessary */
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder ap_listen_rec *lr = apr_pcalloc(s->process->pool, sizeof(ap_listen_rec));
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder apr_sockaddr_info_get(&lr->bind_addr, "0.0.0.0", APR_UNSPEC,
5b3e0bbb6a776c60dc14113435a44e7b13d2fa01Christian Maeder apr_socket_create(&lr->sd, lr->bind_addr->family,
a1a48072301767054f2a9ff7ccf8974b0d6a6a28Christian Maeder for (lr = ap_listeners; lr; lr = lr->next) {
7fe976d9f9c4af1aa7636c568d9919859523de0aChristian Maeder apr_os_sock_put(&lr->sd, &parent_info->listeners[num_listeners].listen_fd, pconf);
38f35f2c4a3b6a778f4f68e7af047a174e93abbeChristian Maeder apr_socket_addr_get(&sa, APR_LOCAL, lr->sd);
0c92a39a4adf3c1cbe173e3b16c65c159a1ce612Christian Maeder /* Do the work */
38f35f2c4a3b6a778f4f68e7af047a174e93abbeChristian Maeder /* Outta here */
0c92a39a4adf3c1cbe173e3b16c65c159a1ce612Christian Maeder /* Parent process */
13140d161d2d2d11d87283d01d57ee3a738a833dChristian Maeder if (ap_setup_listeners(ap_server_conf) < 1) {
13140d161d2d2d11d87283d01d57ee3a738a833dChristian Maeder ap_log_error(APLOG_MARK, APLOG_ALERT, 0, s,
0c92a39a4adf3c1cbe173e3b16c65c159a1ce612Christian Maeder "no listening sockets available, shutting down");
if (!restart) {
static char master_main()
char *listener_shm_name;
set_signals();
return FALSE;
if (rc) {
return FALSE;
if (rc) {
return FALSE;
void *sb_mem;
if (rc) {
return FALSE;
if (one_process) {
return FALSE;
int active_children = 0;
if (rc == 0) {
for (slot=0; ap_scoreboard_image->parent[slot].pid != child_pid && slot < HARD_SERVER_LIMIT; slot++);
return restart_pending;
if (rc) {
static void set_signals()
switch (query_code) {
case AP_MPMQ_MAX_DAEMON_USED:
return APR_SUCCESS;
case AP_MPMQ_IS_THREADED:
return APR_SUCCESS;
case AP_MPMQ_IS_FORKED:
return APR_SUCCESS;
return APR_SUCCESS;
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
return APR_SUCCESS;
return APR_ENOTIMPL;
int ap_graceful_stop_signalled(void)
return is_graceful;
is_graceful = 0;
ap_extended_status = 0;
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
return OK;
static int restart_num = 0;
int startup = 0;
if (restart_num++ == 0) {
if (ap_daemons_to_start < 0) {
if (startup) {
if (startup) {
return OK;
return err;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
return NULL;
{ NULL }