/* 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
*
*
* 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 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 "scoreboard.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
*/
/* Limit on the total number of threads per process
*/
#ifndef HARD_THREAD_LIMIT
#endif
typedef struct {
#define WORKTYPE_CONN 0
static int child_slot;
static int shutdown_pending = 0;
extern int ap_my_generation;
/* 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);
{
if (pchild) {
}
}
{
int requests_this_child = 0;
int rv = 0;
unsigned long ulTimes;
int num_listeners;
void *sb_mem;
/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
set_signals();
/* Create pool for child */
/* Create an event semaphore used to trigger other threads to shutdown */
if (rc) {
"unable to create shutdown semaphore, exiting");
}
/* Gain access to the scoreboard. */
if (rc) {
"scoreboard not readable in child, exiting");
}
/* Gain access to the accpet mutex */
if (rc) {
"accept mutex couldn't be accessed in child, exiting");
}
/* 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) {
"child pid not found in scoreboard, exiting");
}
/* Set up an OS/2 queue for passing connections & termination requests
* to worker threads
*/
if (rc) {
"unable to create work queue, exiting");
}
/* 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 */
/* Set up poll */
}
}
/* Main connection accept loop */
do {
int last_poll_idx = 0;
if (num_listeners == 1) {
} else {
if (shutdown_pending) {
break;
}
if (rv == APR_SUCCESS) {
}
if (rv == APR_SUCCESS) {
if (last_poll_idx >= num_listeners) {
last_poll_idx = 0;
}
}
}
if (rv != APR_SUCCESS) {
if (!APR_STATUS_IS_EINTR(rv)) {
"apr_socket_accept");
}
} else {
}
break;
if (is_graceful) {
char someleft;
/* tell our worker threads to exit */
for (c=0; c<HARD_THREAD_LIMIT; c++) {
}
}
do {
someleft = 0;
for (c=0; c<HARD_THREAD_LIMIT; c++) {
someleft = 1;
DosSleep(1000);
break;
}
}
} while (someleft);
} else {
for (c=0; c<HARD_THREAD_LIMIT; c++) {
}
}
}
}
void add_worker()
{
int thread_slot;
/* Find a free thread slot */
break;
}
}
}
PVOID p)
{
int c;
return XCPT_CONTINUE_SEARCH;
}
"caught exception in worker thread, initiating child shutdown pid=%d", getpid());
for (c=0; c<HARD_THREAD_LIMIT; c++) {
break;
}
}
/* Shut down process ASAP, it could be quite unhealthy & leaking resources */
shutdown_pending = 1;
DosUnwindException(UNWIND_ALL, 0, 0);
}
return XCPT_CONTINUE_SEARCH;
}
{
long conn_id;
int rc;
/* Trap exceptions in this thread so we don't take down the whole process */
if (rc) {
"unable to open work queue, exiting");
}
NULL);
while (rc = DosReadQueue(workq, &rd, &len, (PPVOID)&worker_args, 0, DCWW_WAIT, &priority, NULLHANDLE),
sbh, bucket_alloc);
if (current_conn) {
}
SERVER_READY, NULL);
}
NULL);
}
{
int threadnum;
if (rc) {
"unable to open work queue in maintenance thread");
return;
}
do {
}
if (num_needed > 0) {
add_worker();
}
}
}
}
/* Signal handling routines */
{
shutdown_pending = 1;
is_graceful = 0;
}
{
shutdown_pending = 1;
is_graceful = 1;
}
static void set_signals()
{
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00198) "sigaction(SIGTERM)");
}