📄 mpmt_os2_child.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.
*/
#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 "apr_poll.h"
#include "mpm_common.h"
#include "apr_strings.h"
#include <os2.h>
#include <process.h>
/* XXXXXX move these to header file private to this MPM */
/* 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
#endif
#define ID_FROM_CHILD_THREAD(c, t) ((c * HARD_THREAD_LIMIT) + t)
typedef struct {
apr_pool_t *pconn;
apr_socket_t *conn_sd;
} worker_args_t;
#define WORKTYPE_CONN 0
#define WORKTYPE_EXIT 1
static apr_pool_t *pchild = NULL;
static int child_slot;
static int shutdown_pending = 0;
extern int ap_my_generation;
static int volatile is_graceful = 1;
HEV shutdown_event; /* signaled when this child is shutting down */
/* grab some MPM globals */
extern int ap_min_spare_threads;
extern int ap_max_spare_threads;
extern HMTX ap_mpm_accept_mutex;
static void worker_main(void *vpArg);
static void clean_child_exit(int code);
static void set_signals();
static void server_maintenance(void *vpArg);
static void clean_child_exit(int code)
{
if (pchild) {
apr_pool_destroy(pchild);
}
exit(code);
}
void ap_mpm_child_main(apr_pool_t *pconf)
{
ap_listen_rec *lr = NULL;
ap_listen_rec *first_lr = NULL;
int requests_this_child = 0;
apr_socket_t *sd = ap_listeners->sd;
int nsds, rv = 0;
unsigned long ulTimes;
int my_pid = getpid();
ULONG rc, c;
HQUEUE workq;
apr_pollfd_t *pollset;
int num_listeners;
TID server_maint_tid;
void *sb_mem;
/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
DosSetSignalExceptionFocus(0, &ulTimes);
set_signals();
/* Create pool for child */
apr_pool_create(&pchild, pconf);
ap_run_child_init(pchild, ap_server_conf);
/* Create an event semaphore used to trigger other threads to shutdown */
rc = DosCreateEventSem(NULL, &shutdown_event, 0, FALSE);
if (rc) {
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
"unable to create shutdown semaphore, exiting");
clean_child_exit(APEXIT_CHILDFATAL);
}
/* Gain access to the scoreboard. */
rc = DosGetNamedSharedMem(&sb_mem, ap_scoreboard_fname,
PAG_READ|PAG_WRITE);
if (rc) {
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
"scoreboard not readable in child, exiting");
clean_child_exit(APEXIT_CHILDFATAL);
}
ap_calc_scoreboard_size();
ap_init_scoreboard(sb_mem);
/* Gain access to the accpet mutex */
rc = DosOpenMutexSem(NULL, &ap_mpm_accept_mutex);
if (rc) {
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
"accept mutex couldn't be accessed in child, exiting");
clean_child_exit(APEXIT_CHILDFATAL);
}
/* Find our pid in the scoreboard so we know what slot our parent allocated us */
for (child_slot = 0; ap_scoreboard_image->parent[child_slot].pid != my_pid && child_slot < HARD_SERVER_LIMIT; child_slot++);
if (child_slot == HARD_SERVER_LIMIT) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
"child pid not found in scoreboard, exiting");
clean_child_exit(APEXIT_CHILDFATAL);
}
ap_my_generation = ap_scoreboard_image->parent[child_slot].generation;
memset(ap_scoreboard_image->servers[child_slot], 0, sizeof(worker_score) * HARD_THREAD_LIMIT);
/* Set up an OS/2 queue for passing connections & termination requests
* to worker threads
*/
rc = DosCreateQueue(&workq, QUE_FIFO, apr_psprintf(pchild, "/queues/httpd/work.%d", my_pid));
if (rc) {
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
"unable to create work queue, exiting");
clean_child_exit(APEXIT_CHILDFATAL);
}
/* Create initial pool of worker threads */
for (c = 0; c < ap_min_spare_threads; c++) {
// ap_scoreboard_image->servers[child_slot][c].tid = _beginthread(worker_main, NULL, 128*1024, (void *)c);
}
/* Start maintenance thread */
server_maint_tid = _beginthread(server_maintenance, NULL, 32768, NULL);
/* Set up poll */
for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) {
num_listeners++;
}
apr_poll_setup(&pollset, num_listeners, pchild);
for (lr = ap_listeners; lr; lr = lr->next) {
apr_poll_socket_add(pollset, lr->sd, APR_POLLIN);
}
/* Main connection accept loop */
do {
apr_pool_t *pconn;
worker_args_t *worker_args;
apr_pool_create(&pconn, pchild);
worker_args = apr_palloc(pconn, sizeof(worker_args_t));
worker_args->pconn = pconn;
if (num_listeners == 1) {
rv = apr_accept(&worker_args->conn_sd, ap_listeners->sd, pconn);
} else {
rc = DosRequestMutexSem(ap_mpm_accept_mutex, SEM_INDEFINITE_WAIT);
if (shutdown_pending) {
DosReleaseMutexSem(ap_mpm_accept_mutex);
break;
}
rv = APR_FROM_OS_ERROR(rc);
if (rv == APR_SUCCESS) {
rv = apr_poll(pollset, num_listeners, &nsds, -1);
DosReleaseMutexSem(ap_mpm_accept_mutex);
}
if (rv == APR_SUCCESS) {
if (first_lr == NULL) {
first_lr = ap_listeners;
}
lr = first_lr;
do {
apr_int16_t event;
apr_poll_revents_get(&event, lr->sd, pollset);
if (event == APR_POLLIN) {
apr_sockaddr_t *sa;
apr_port_t port;
apr_socket_addr_get(&sa, APR_LOCAL, lr->sd);
apr_sockaddr_port_get(&port, sa);
first_lr = lr->next;
break;
}
lr = lr->next;
if (!lr) {
lr = ap_listeners;
}
} while (lr != first_lr);
if (lr == first_lr) {
continue;
}
sd = lr->sd;
rv = apr_accept(&worker_args->conn_sd, sd, pconn);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -