mpm_netware.c revision 09a1167b8cb70e15be9f661f9e83ee33cfe062de
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Unless required by applicable law or agreed to in writing, software
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distributed under the License is distributed on an "AS IS" BASIS,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * See the License for the specific language governing permissions and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * limitations under the License.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * httpd.c: simple http daemon for answering WWW file requests
e8f95a682820a599fe41b22977010636be5c2717jim * 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 03-06-95 blong
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * changed server number for child-alone processes to 0 and changed name
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * of processes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 03-10-95 blong
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * including set group before fork, and call gettime before to fork
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * to set up libraries.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 04-14-95 rst / rh
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Apache server, and also to have child processes do accept() directly.
5c0419d51818eb02045cf923a9fe456127a44c60wrowe * April-July '95 rst
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Extensive rework for Apache.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Limit on the total --- clients will be locked out if more servers than
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * this are needed. It is intended solely to keep the server from crashing
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * when things get out of hand.
796e4a7141265d8ed7036e4628161c6eafb2a789jorton * We keep a hard maximum number of servers, for two reasons --- first off,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * in case something goes seriously wrong, we want to stop the fork bomb
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * short of actually crashing the machine we're running on by filling some
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * kernel table. Secondly, it keeps the size of the scoreboard file small
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * enough that we can read the whole thing without worrying too much about
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the overhead.
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin/* config globals */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* *Non*-shared http_main globals... */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int ap_threads_per_child=0; /* Worker threads per child */
a1790fb35c4b352dab721370985c623a9f8f5062rpluem * The max child slot ever assigned, preserved across restarts. Necessary
713a2b68bac4aeb1e9c48785006c0732451039depquerna * to deal with MaxClients changes across SIGWINCH restarts. We use this
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * value to optimize routines that have to scan the entire scoreboard.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesint hold_screen_on_exit = 0; /* Indicates whether the screen should be held open */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_pool_t *pconf; /* Pool for config stuff */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_pool_t *pmain; /* Pool for httpd child stuff */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic pid_t ap_my_pid; /* it seems silly to call getpid all the time */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic int die_now = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Keep track of the number of worker threads currently active */
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholesstatic unsigned long worker_thread_count;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe/* Structure used to register/deregister a console handler with the OS */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int InstallConsoleHandler(void);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void RemoveConsoleHandler(void);
fa123db15501821e36e513afa78e839775ad2800covenerstatic int CommandLineInterpreter(scr_t screenID, const char *commandLine);
fa123db15501821e36e513afa78e839775ad2800covenerstatic CommandParser_t ConsoleHandler = {0, NULL, 0};
fa123db15501821e36e513afa78e839775ad2800covenerstatic int show_settings = 0;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener//#define DBINFO_ON
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim//#define DBPRINT_ON
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* volatile just in case */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int volatile shutdown_pending;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int volatile restart_pending;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic int volatile is_graceful;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* a clean exit from a child with proper cleanup */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void clean_child_exit(int code, int worker_num, apr_pool_t *ptrans,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_bucket_alloc_t *bucket_alloc) __attribute__ ((noreturn));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void clean_child_exit(int code, int worker_num, apr_pool_t *ptrans,
cceddc0b6c0fdaed0c73abda39975bb1d388243acovener ap_update_child_status_from_indexes(0, worker_num, WORKER_DEAD,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener/* proper cleanup when returning from ap_mpm_run() */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic void mpm_main_cleanup(void)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic int netware_query(int query_code, int *result, apr_status_t *rv)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic apr_status_t netware_note_child_killed(int childnum)
465bb68501690d7a47bfd2a6129580047d76d8f1rederpjstatic const char *netware_get_name(void)
465bb68501690d7a47bfd2a6129580047d76d8f1rederpj return "NetWare";
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes/*****************************************************************
55e2e59e5910072e51c870afc68b0907f41a28e0sf * Connection structures and accounting...
55e2e59e5910072e51c870afc68b0907f41a28e0sfstatic void mpm_term(void)
55e2e59e5910072e51c870afc68b0907f41a28e0sf /* Um, is this _probably_ not an error, if the user has
55e2e59e5910072e51c870afc68b0907f41a28e0sf * tried to do a shutdown twice quickly, so we won't
55e2e59e5910072e51c870afc68b0907f41a28e0sf * worry about reporting it.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* restart() is the signal handler for SIGHUP and SIGWINCH
513b324e774c559b579896df131fd7c8471ed529rederpj * in the parent process, unless running in ONE_PROCESS mode
513b324e774c559b579896df131fd7c8471ed529rederpjstatic void restart(void)
513b324e774c559b579896df131fd7c8471ed529rederpj /* Probably not an error - don't bother reporting it */
02fd88c85a9850109753b87612955ad372de1575sfstatic void set_signals(void)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf/*****************************************************************
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * Child process main loop.
185aa71728867671e105178b4c66fbc22b65ae26sf * The following vars are static to avoid getting clobbered by longjmp();
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * they are really private to child_main.
9ad7b260be233be7d7b5576979825cac72e15498rederpjstatic int would_block = 0;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic int retry_success = 0;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic int retry_fail = 0;
54d22ed1c429b903b029bbd62621f11a9e286137minfrinstatic int avg_retries = 0;
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf/*static */
b08925593f214f621161742925dcf074a8047e0acovener apr_allocator_max_free_set(allocator, ap_max_mem_free);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_pool_create_ex(&ptrans, pmain, NULL, allocator);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener bucket_alloc = apr_bucket_alloc_create_ex(allocator);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * (Re)initialize this child to a pre-connection state.
707f6d077f73cc948deead8df5b40ea42c1eaa78covener && requests_this_child++ >= ap_max_requests_per_child)) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener DBPRINT1 ("\n**Thread slot %d is shutting down", my_worker_num);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener clean_child_exit(0, my_worker_num, ptrans, bucket_alloc);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener ap_update_child_status_from_indexes(0, my_worker_num, WORKER_READY,
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * Wait for an acceptable connection to arrive.
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf for (;;) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (shutdown_pending || restart_pending || (ap_scoreboard_image->servers[0][my_worker_num].status == WORKER_IDLE_KILL)) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener DBPRINT1 ("\nThread slot %d is shutting down\n", my_worker_num);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener clean_child_exit(0, my_worker_num, ptrans, bucket_alloc);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener /* Check the listen queue on all sockets for requests */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener srv = select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (srv <= 0) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
9ad7b260be233be7d7b5576979825cac72e15498rederpj "select() failed on listen socket");
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* remember the last_lr we searched last time around so that
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf we don't end up starving any particular listening socket */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* if we get here, something unexpected happened. Go back
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf into the select state and try again.
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if ((stat = apr_socket_accept(&csd, sd, ptrans)) == APR_SUCCESS) {
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes /* if the error is a wouldblock then maybe we were too
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes quick try to pull the next request from the listen
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes queue. Try a few more times then return to our idle
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes listen state. */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* If we got a new socket, set it to non-blocking mode and process
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf it. Otherwise handle the error. */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes break; /* We have a socket ready for reading */
7dbf29be626018bc389ef94c1846aeac4b72633bsf * When the network layer has been shut down, there
7dbf29be626018bc389ef94c1846aeac4b72633bsf * is not much use in simply exiting: the parent
7dbf29be626018bc389ef94c1846aeac4b72633bsf * would simply re-create us (and we'd fail again).
7dbf29be626018bc389ef94c1846aeac4b72633bsf * Use the CHILDFATAL code to tear the server down.
7dbf29be626018bc389ef94c1846aeac4b72633bsf * @@@ Martin's idea for possible improvement:
7dbf29be626018bc389ef94c1846aeac4b72633bsf * A different approach would be to define
7dbf29be626018bc389ef94c1846aeac4b72633bsf * a new APEXIT_NETDOWN exit code, the reception
7dbf29be626018bc389ef94c1846aeac4b72633bsf * of which would make the parent shutdown all
783874b86bfe13d7a4fe0922f344a3779cdccea3covener * children, then idle-loop until it detected that
7dbf29be626018bc389ef94c1846aeac4b72633bsf * the network is up again, and restart the children.
7dbf29be626018bc389ef94c1846aeac4b72633bsf * Ben Hyde noted that temporary ENETDOWN situations
7dbf29be626018bc389ef94c1846aeac4b72633bsf * occur in mobile IP.
7dbf29be626018bc389ef94c1846aeac4b72633bsf ap_log_error(APLOG_MARK, APLOG_EMERG, stat, ap_server_conf,
783874b86bfe13d7a4fe0922f344a3779cdccea3covener "apr_socket_accept: giving up.");
7dbf29be626018bc389ef94c1846aeac4b72633bsf clean_child_exit(APEXIT_CHILDFATAL, my_worker_num, ptrans,
7dbf29be626018bc389ef94c1846aeac4b72633bsf ap_log_error(APLOG_MARK, APLOG_ERR, stat, ap_server_conf,
7dbf29be626018bc389ef94c1846aeac4b72633bsf "apr_socket_accept: (client socket)");
783874b86bfe13d7a4fe0922f344a3779cdccea3covener clean_child_exit(1, my_worker_num, ptrans, bucket_alloc);
7dbf29be626018bc389ef94c1846aeac4b72633bsf * We now have a connection, so set it up with the appropriate
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * socket options, file descriptors, and read/write buffers.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf clean_child_exit(0, my_worker_num, ptrans, bucket_alloc);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_update_child_status_from_indexes(0, slot, WORKER_STARTING,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (ctx = NXContextAlloc((void (*)(void *)) worker_main, (void*)slot, NX_PRIO_MED, ap_thread_stacksize, NX_CTX_NORMAL, &err)) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes err = NXThreadCreate(ctx, NX_THR_BIND_CONTEXT, &tid);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* create thread didn't succeed. Fix the scoreboard or else
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * it will say SERVER_STARTING forever and ever
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener ap_update_child_status_from_indexes(0, slot, WORKER_DEAD,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* In case system resources are maxxed out, we don't want
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf Apache running away with the CPU trying to fork over and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes over and over again. */
7dbf29be626018bc389ef94c1846aeac4b72633bsf/* start up a bunch of worker threads */
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener for (i = 0; number_to_start && i < ap_threads_limit; ++i) {
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if (ap_scoreboard_image->servers[0][i].status != WORKER_DEAD) {
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener * idle_spawn_rate is the number of children that will be spawned on the
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener * next maintenance cycle if there aren't enough idle servers. It is
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener * without the need to spawn.
9c63a05713cb83a44a1590b4af33edeebf39f118sfstatic void perform_idle_server_maintenance(apr_pool_t *p)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* initialize the free_list */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin for (i = 0; i < ap_threads_limit; ++i) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (i >= ap_max_workers_limit && free_length == idle_spawn_rate)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* try to keep children numbers as low as possible */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* If it is already marked to die, skip it */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* We consider a starting server as idle because we started it
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * at least a cycle ago, and if it still hasn't finished starting
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * then we're just going to swamp things worse by forking more.
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * So we hopefully won't need to fork more if we count it.
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * This depends on the ordering of SERVER_READY and SERVER_STARTING.
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener DBPRINT2("Total: %d Idle Count: %d \r", total_non_dead, idle_count);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* kill off one child... we use the pod because that'll cause it to
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * shut down gracefully, in case it happened to pick up a request
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * while we were counting
54d22ed1c429b903b029bbd62621f11a9e286137minfrin ap_update_child_status_from_indexes(0, last_non_dead, WORKER_IDLE_KILL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DBPRINT1("\nKilling idle thread: %d\n", last_non_dead);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* terminate the free list */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* only report this condition once */
e8f95a682820a599fe41b22977010636be5c2717jim static int reported = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
e8f95a682820a599fe41b22977010636be5c2717jim "server reached MaxClients setting, consider"
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe " raising the MaxClients setting");
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "server seems busy, (you may need "
e8f95a682820a599fe41b22977010636be5c2717jim "to increase StartServers, or Min/MaxSpareServers), "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "spawning %d children, there are %d idle, and "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (i = 0; i < free_length; ++i) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DBPRINT1("Spawning additional thread slot: %d\n", free_slots[i]);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* the next time around we want to spawn twice as many if this
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * wasn't good enough, but not if we've just done a graceful
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener for (i=0;i<SERVER_NUM_STATUS;i++) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (i = 0; i < ap_threads_limit; ++i) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes status = (ap_scoreboard_image->servers[0][i]).status;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (i=0;i<SERVER_NUM_STATUS;i++) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes printf ("Unknown Status:\t%d\n", status_array[i]);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes printf ("Total Running:\t%d\tout of: \t%d\n", total, ap_threads_limit);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes printf ("Successful retries:\t%d\n", retry_success);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes printf ("Avg retries:\t%d\n", retry_success == 0 ? 0 : avg_retries / retry_success);
ebe5305f8b22507374358f32b74d12fb50c05a25covener if (ap_my_addrspace && (ap_my_addrspace[0] != 'O') && (ap_my_addrspace[1] != 'S'))
ebe5305f8b22507374358f32b74d12fb50c05a25covener printf(" Running in address space %s\n", ap_my_addrspace);
ebe5305f8b22507374358f32b74d12fb50c05a25covener /* Display listening ports */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* Display dynamic modules loaded */
0e05808dc59a321566303084c84b9826a4353cefrederpj printf(" Loaded dynamic module %s\n", ((module*)*m)->name);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "no listening sockets available, shutting down");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*****************************************************************
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Executive routines.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int netware_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "no listening sockets available, shutting down");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ap_run_pre_mpm(s->process->pool, SB_NOT_SHARED) != OK) {
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe /* Only set slot 0 since that is all NetWare will ever have. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ap_threads_max_free < ap_threads_min_free + 1) /* Don't thrash... */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Allow the Apache screen to be closed normally on exit() only if it
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes has not been explicitly forced to close on exit(). (ie. the -E flag
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes was specified at startup) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "%s configured -- resuming normal operations",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Shutdown the listen sockets so that we don't get stuck in a blocking call.
e8f95a682820a599fe41b22977010636be5c2717jim shutdown_listeners();*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (shutdown_pending) { /* Got an unload from the console */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "caught SIGTERM, shutting down");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes printf ("\rShutdown pending. Waiting for %d thread(s) to terminate...",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else { /* the only other way out is a restart */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* advance to the next generation */
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener /* XXX: we really need to make sure this new generation number isn't in
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * use by any of the children.
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener ap_scoreboard_image->global->running_generation = ap_my_generation;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener "Graceful restart requested, doing restart");
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes /* Wait for all of the threads to terminate before initiating the restart */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes printf ("\rRestart pending. Waiting for %d thread(s) to terminate...",
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholesstatic int netware_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* The following call has been moved to the mod_nw_ssl pre-config handler */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int netware_check_config(apr_pool_t *p, apr_pool_t *plog,
e8f95a682820a599fe41b22977010636be5c2717jim static int restart_num = 0;
e8f95a682820a599fe41b22977010636be5c2717jim /* we want this only the first time around */
e8f95a682820a599fe41b22977010636be5c2717jim if (restart_num++ == 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "WARNING: MaxThreads of %d exceeds compile-time "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes " %d threads, decreasing to %d.",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes " To increase, please see the HARD_THREAD_LIMIT"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "define in");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "MaxThreads of %d exceeds compile-time limit "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "of %d, decreasing to match",
e8f95a682820a599fe41b22977010636be5c2717jim ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "WARNING: MaxThreads of %d not allowed, "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "MaxThreads of %d not allowed, increasing to 1",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ap_threads_to_start > ap_threads_limit effectively checked in
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * call to startup_workers(ap_threads_to_start) in ap_mpm_run()
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "WARNING: StartThreads of %d not allowed, "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "StartThreads of %d not allowed, increasing to 1",
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj "WARNING: MinSpareThreads of %d not allowed, "
e8f95a682820a599fe41b22977010636be5c2717jim ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe " to avoid almost certain server failure.");
e8f95a682820a599fe41b22977010636be5c2717jim ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes " Please read the documentation.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "MinSpareThreads of %d not allowed, increasing to 1",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ap_threads_max_free < ap_threads_min_free + 1 checked in ap_mpm_run() */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_pre_config(netware_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_check_config(netware_check_config, NULL, NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes //ap_hook_post_config(netware_post_config, NULL, NULL, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes //ap_hook_child_init(netware_child_init, NULL, NULL, APR_HOOK_MIDDLE);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj //ap_hook_open_logs(netware_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ap_hook_mpm(netware_run, NULL, NULL, APR_HOOK_MIDDLE);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ap_hook_mpm_query(netware_query, NULL, NULL, APR_HOOK_MIDDLE);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ap_hook_mpm_note_child_killed(netware_note_child_killed, NULL, NULL, APR_HOOK_MIDDLE);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ap_hook_mpm_get_name(netware_get_name, NULL, NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void netware_rewrite_args(process_rec *process)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *opt_arg;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener /* Make sure to hold the Apache screen open if exit() is called */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Rewrite process->argv[];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * add default -d serverroot from the path of this executable
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener * The end result will look like:
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener * The -d serverroot default from the running executable
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim char *s = apr_pstrdup (process->pconf, process->argv[0]);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener for (i=len; i; i--) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s[i] = '\0';
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* Use process->pool so that the rewritten argv
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * lasts for the lifetime of the server process,
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener * because pconf will be destroyed after the
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * initial pre-flight of the config parser.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes mpm_new_argv = apr_array_make(process->pool, process->argc + 2,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sizeof(const char *));
e8f95a682820a599fe41b22977010636be5c2717jim *(const char **)apr_array_push(mpm_new_argv) = process->argv[0];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *(const char **)apr_array_push(mpm_new_argv) = "-d";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *(const char **)apr_array_push(mpm_new_argv) = def_server_root;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_getopt_init(&opt, process->pool, process->argc, (char**) process->argv);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (apr_getopt(opt, AP_SERVER_BASEARGS"n:", optbuf + 1, &opt_arg) == APR_SUCCESS) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* Don't need to hold the screen open if the output is going to a file */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj *(const char **)apr_array_push(mpm_new_argv) = opt_arg;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj process->argv = (const char * const *) mpm_new_argv->elts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int CommandLineInterpreter(scr_t screenID, const char *commandLine)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_cpystrn(szcommandLine, commandLine, sizeof(szcommandLine));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* All added commands begin with "APACHE2 " */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!strnicmp(szCommand, szcommandLine, iCommandLen)) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* If an instance id was not given but the nlm is loaded in
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem protected space, then the the command belongs to the
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem OS address space instance to pass it on. */
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* If we got an instance id but it doesn't match this
8869662bb1a4078297020e94ae5e928626d877c6rederpj instance of the nlm, pass it on. */
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener if (pID && ap_my_addrspace && strnicmp(pID, ap_my_addrspace, strlen(ap_my_addrspace)))
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* If we have determined that this command belongs to this
8869662bb1a4078297020e94ae5e928626d877c6rederpj instance of the nlm, then handle it. */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (!strnicmp("RESTART",&szcommandLine[iCommandLen],3)) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem else if (!strnicmp("VERSION",&szcommandLine[iCommandLen],3)) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem printf("Server version: %s\n", ap_get_server_description());
8869662bb1a4078297020e94ae5e928626d877c6rederpj else if (!strnicmp("MODULES",&szcommandLine[iCommandLen],3)) {
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener else if (!strnicmp("DIRECTIVES",&szcommandLine[iCommandLen],3)) {
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener else if (!strnicmp("SHUTDOWN",&szcommandLine[iCommandLen],3)) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj else if (!strnicmp("SETTINGS",&szcommandLine[iCommandLen],3)) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf printf("Unknown APACHE2 command %s\n", &szcommandLine[iCommandLen]);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf printf("\tMODULES - Show a list of the loaded modules\n");
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf printf("\tRESTART - Reread the configuration file and restart Apache\n");
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener printf("\tSETTINGS - Show current thread status\n");
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf printf("\tVERSION - Display the server version information\n");
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* Tell NetWare we handled the command */
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* Tell NetWare that the command isn't mine */
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic int InstallConsoleHandler(void)
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* Our command line handler interfaces the system operator
8869662bb1a4078297020e94ae5e928626d877c6rederpj with this NLM */
8869662bb1a4078297020e94ae5e928626d877c6rederpj NX_WRAP_INTERFACE(CommandLineInterpreter, 2, (void*)&(ConsoleHandler.parser));
8869662bb1a4078297020e94ae5e928626d877c6rederpj ConsoleHandler.rTag = AllocateResourceTag(getnlmhandle(), "Command Line Processor",
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* The Remove procedure unregisters the console handler */
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic void RemoveConsoleHandler(void)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic const char *set_threads_to_start(cmd_parms *cmd, void *dummy, const char *arg)
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic const char *set_min_free_threads(cmd_parms *cmd, void *dummy, const char *arg)
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic const char *set_max_free_threads(cmd_parms *cmd, void *dummy, const char *arg)
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *arg)
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpjAP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF,
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj "Number of worker threads launched at server startup"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemAP_INIT_TAKE1("MinSpareThreads", set_min_free_threads, NULL, RSRC_CONF,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Minimum number of idle threads, to handle request spikes"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemAP_INIT_TAKE1("MaxSpareThreads", set_max_free_threads, NULL, RSRC_CONF,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Maximum number of idle threads"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemAP_INIT_TAKE1("MaxThreads", set_thread_limit, NULL, RSRC_CONF,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Maximum number of worker threads alive at the same time"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem netware_rewrite_args, /* hook to run before apache parses args */