/* 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 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 maintenance * thread so that the number of idle threads is kept between * min_spare_threads & max_spare_threads. *
*/
/* Todo list - Enforce MaxRequestWorkers somehow
*/ #define INCL_NOPMAPI #define INCL_DOS #define INCL_DOSERRORS
/* Keep track of a few interesting statistics */ int ap_max_daemons_limit = 0;
/* volatile just in case */ staticintvolatile shutdown_pending; staticintvolatile restart_pending; staticintvolatile is_graceful = 0;
ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */ staticint 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
*/ typedefstruct { struct sockaddr_in name;
apr_os_sock_t listen_fd;
} listen_socket_t;
/* 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()
*/
while (!restart_pending && !shutdown_pending) {
RESULTCODES proc_rc;
PID child_pid; int active_children = 0;
/* Count number of active children */ for (slot=0; slot < HARD_SERVER_LIMIT; slot++) {
active_children += ap_scoreboard_image->parent[slot].pid != 0 &&
!ap_scoreboard_image->parent[slot].quiescing;
}
/* Spawn children if needed */ for (slot=0; slot < HARD_SERVER_LIMIT && active_children < ap_daemons_to_start; slot++) { if (ap_scoreboard_image->parent[slot].pid == 0) {
spawn_child(slot);
active_children++;
}
}
if (rc == 0) { /* A child has terminated, remove its scoreboard entry & terminate if necessary */ for (slot=0; ap_scoreboard_image->parent[slot].pid != child_pid && slot < HARD_SERVER_LIMIT; slot++);
if (proc_rc.codeTerminate == TC_EXIT) { /* Child terminated normally, check its exit code and * terminate server if child indicates a fatal error
*/ if (proc_rc.codeResult == APEXIT_CHILDFATAL) break;
}
}
} elseif (rc == ERROR_CHILD_NOT_COMPLETE) { /* No child exited, lets sleep for a while.... */
apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL);
}
}
/* Signal children to shut down, either gracefully or immediately */ for (slot=0; slot<HARD_SERVER_LIMIT; slot++) {
kill(ap_scoreboard_image->parent[slot].pid, is_graceful ? SIGHUP : SIGTERM);
}
DosFreeMem(parent_info); return restart_pending ? OK : DONE;
}
/* we want this only the first time around */ if (restart_num++ == 0) {
startup = 1;
}
if (ap_daemons_to_start < 0) { if (startup) {
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00213) "WARNING: StartServers of %d not allowed, " "increasing to 1.", ap_daemons_to_start);
} else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00214) "StartServers of %d not allowed, increasing to 1",
ap_daemons_to_start);
}
ap_daemons_to_start = 1;
}
if (ap_min_spare_threads < 1) { if (startup) {
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00215) "WARNING: MinSpareThreads of %d not allowed, " "increasing to 1 to avoid almost certain server failure. " "Please read the documentation.", ap_min_spare_threads);
} else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00216) "MinSpareThreads of %d not allowed, increasing to 1",
ap_min_spare_threads);
}
ap_min_spare_threads = 1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.