📄 mpmt_os2.c
字号:
/* 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. *//* Multi-process, multi-threaded MPM for OS/2 * * Server consists of * - a main, parent process * - a small, static number of child processes * * The parent process's job is to manage the child processes. This involves * spawning children as required to ensure there are always ap_daemons_to_start * processes accepting connections. * * Each child process consists of a a pool of worker threads and a * main thread that accepts connections & passes them to the workers via * a work queue. The worker thread pool is dynamic, managed by a maintanence * thread so that the number of idle threads is kept between * min_spare_threads & max_spare_threads. * *//* Todo list - Enforce MaxClients somehow*/#define CORE_PRIVATE#define INCL_NOPMAPI#define INCL_DOS#define INCL_DOSERRORS#include "ap_config.h"#include "httpd.h"#include "mpm_default.h"#include "http_main.h"#include "http_log.h"#include "http_config.h"#include "http_core.h" /* for get_remote_host */#include "http_connection.h"#include "mpm.h"#include "ap_mpm.h"#include "ap_listen.h"#include "apr_portable.h"#include "mpm_common.h"#include "apr_strings.h"#include <os2.h>#include <process.h>/* We don't need many processes, * they're only for redundancy in the event of a crash */#define HARD_SERVER_LIMIT 10/* Limit on the total number of threads per process */#ifndef HARD_THREAD_LIMIT#define HARD_THREAD_LIMIT 256#endifserver_rec *ap_server_conf;static apr_pool_t *pconf = NULL; /* Pool for config stuff */static const char *ap_pid_fname=NULL;/* Config globals */static int one_process = 0;static int ap_daemons_to_start = 0;static int ap_thread_limit = 0;static int ap_max_requests_per_child = 0;int ap_min_spare_threads = 0;int ap_max_spare_threads = 0;/* Keep track of a few interesting statistics */int ap_max_daemons_limit = -1;/* volatile just in case */static int volatile shutdown_pending;static int volatile restart_pending;static int volatile is_graceful = 0;ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */static int is_parent_process=TRUE;HMTX ap_mpm_accept_mutex = 0;/* An array of these is stored in a shared memory area for passing * sockets from the parent to child processes */typedef struct { struct sockaddr_in name; apr_os_sock_t listen_fd;} listen_socket_t;typedef struct { HMTX accept_mutex; listen_socket_t listeners[1];} parent_info_t;static char master_main();static void spawn_child(int slot);void ap_mpm_child_main(apr_pool_t *pconf);static void set_signals();int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s ){ char *listener_shm_name; parent_info_t *parent_info; ULONG rc; pconf = _pconf; ap_server_conf = s; restart_pending = 0; DosSetMaxFH(ap_thread_limit * 2); listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getppid()); rc = DosGetNamedSharedMem((PPVOID)&parent_info, listener_shm_name, PAG_READ); is_parent_process = rc != 0; ap_scoreboard_fname = apr_psprintf(pconf, "/sharemem/httpd/scoreboard.%d", is_parent_process ? getpid() : getppid()); if (rc == 0) { /* Child process */ ap_listen_rec *lr; int num_listeners = 0; ap_mpm_accept_mutex = parent_info->accept_mutex; /* Set up a default listener if necessary */ if (ap_listeners == NULL) { ap_listen_rec *lr = apr_pcalloc(s->process->pool, sizeof(ap_listen_rec)); ap_listeners = lr; apr_sockaddr_info_get(&lr->bind_addr, "0.0.0.0", APR_UNSPEC, DEFAULT_HTTP_PORT, 0, s->process->pool); apr_socket_create(&lr->sd, lr->bind_addr->family, SOCK_STREAM, s->process->pool); } for (lr = ap_listeners; lr; lr = lr->next) { apr_sockaddr_t *sa; apr_os_sock_put(&lr->sd, &parent_info->listeners[num_listeners].listen_fd, pconf); apr_socket_addr_get(&sa, APR_LOCAL, lr->sd); num_listeners++; } DosFreeMem(parent_info); /* Do the work */ ap_mpm_child_main(pconf); /* Outta here */ return 1; } else { /* Parent process */ char restart; is_parent_process = TRUE; if (ap_setup_listeners(ap_server_conf) < 1) { ap_log_error(APLOG_MARK, APLOG_ALERT, 0, s, "no listening sockets available, shutting down"); return 1; } ap_log_pid(pconf, ap_pid_fname); restart = master_main(); ++ap_my_generation; ap_scoreboard_image->global->running_generation = ap_my_generation; if (!restart) { const char *pidfile = ap_server_root_relative(pconf, ap_pid_fname); if (pidfile != NULL && remove(pidfile) == 0) { ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf, "removed PID file %s (pid=%d)", pidfile, getpid()); } ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "caught SIGTERM, shutting down"); return 1; } } /* Parent process */ return 0; /* Restart */}/* Main processing of the parent process * returns TRUE if restarting */static char master_main(){ server_rec *s = ap_server_conf; ap_listen_rec *lr; parent_info_t *parent_info; char *listener_shm_name; int listener_num, num_listeners, slot; ULONG rc; printf("%s \n", ap_get_server_version()); set_signals(); if (ap_setup_listeners(ap_server_conf) < 1) { ap_log_error(APLOG_MARK, APLOG_ALERT, 0, s, "no listening sockets available, shutting down"); return FALSE; } /* Allocate a shared memory block for the array of listeners */ for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) { num_listeners++; } listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getpid()); rc = DosAllocSharedMem((PPVOID)&parent_info, listener_shm_name, sizeof(parent_info_t) + num_listeners * sizeof(listen_socket_t), PAG_READ|PAG_WRITE|PAG_COMMIT); if (rc) { ap_log_error(APLOG_MARK, APLOG_ALERT, APR_FROM_OS_ERROR(rc), s, "failure allocating shared memory, shutting down"); return FALSE; } /* Store the listener sockets in the shared memory area for our children to see */ for (listener_num = 0, lr = ap_listeners; lr; lr = lr->next, listener_num++) { apr_os_sock_get(&parent_info->listeners[listener_num].listen_fd, lr->sd); } /* Create mutex to prevent multiple child processes from detecting * a connection with apr_poll() */ rc = DosCreateMutexSem(NULL, &ap_mpm_accept_mutex, DC_SEM_SHARED, FALSE); if (rc) { ap_log_error(APLOG_MARK, APLOG_ALERT, APR_FROM_OS_ERROR(rc), s, "failure creating accept mutex, shutting down"); return FALSE; } parent_info->accept_mutex = ap_mpm_accept_mutex; /* Allocate shared memory for scoreboard */ if (ap_scoreboard_image == NULL) { void *sb_mem; rc = DosAllocSharedMem(&sb_mem, ap_scoreboard_fname, ap_calc_scoreboard_size(), PAG_COMMIT|PAG_READ|PAG_WRITE); if (rc) { ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf, "unable to allocate shared memory for scoreboard , exiting"); return FALSE; } ap_init_scoreboard(sb_mem); } ap_scoreboard_image->global->restart_time = apr_time_now(); ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "%s configured -- resuming normal operations", ap_get_server_version()); ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, "Server built: %s", ap_get_server_built());#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "AcceptMutex: %s (default: %s)", apr_proc_mutex_name(accept_mutex), apr_proc_mutex_defname());#endif if (one_process) { ap_scoreboard_image->parent[0].pid = getpid(); ap_mpm_child_main(pconf); return FALSE; } while (!restart_pending && !shutdown_pending) { RESULTCODES proc_rc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -