home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / main / http_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-08  |  168.6 KB  |  6,147 lines

  1. /* ====================================================================
  2.  * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer. 
  10.  *
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in
  13.  *    the documentation and/or other materials provided with the
  14.  *    distribution.
  15.  *
  16.  * 3. All advertising materials mentioning features or use of this
  17.  *    software must display the following acknowledgment:
  18.  *    "This product includes software developed by the Apache Group
  19.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  20.  *
  21.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  22.  *    endorse or promote products derived from this software without
  23.  *    prior written permission. For written permission, please contact
  24.  *    apache@apache.org.
  25.  *
  26.  * 5. Products derived from this software may not be called "Apache"
  27.  *    nor may "Apache" appear in their names without prior written
  28.  *    permission of the Apache Group.
  29.  *
  30.  * 6. Redistributions of any form whatsoever must retain the following
  31.  *    acknowledgment:
  32.  *    "This product includes software developed by the Apache Group
  33.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  36.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Group and was originally based
  51.  * on public domain software written at the National Center for
  52.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  53.  * For more information on the Apache Group and the Apache HTTP server
  54.  * project, please see <http://www.apache.org/>.
  55.  *
  56.  */
  57.  
  58. /*
  59.  * httpd.c: simple http daemon for answering WWW file requests
  60.  *
  61.  * 
  62.  * 03-21-93  Rob McCool wrote original code (up to NCSA HTTPd 1.3)
  63.  * 
  64.  * 03-06-95  blong
  65.  *  changed server number for child-alone processes to 0 and changed name
  66.  *   of processes
  67.  *
  68.  * 03-10-95  blong
  69.  *      Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu) 
  70.  *      including set group before fork, and call gettime before to fork
  71.  *      to set up libraries.
  72.  *
  73.  * 04-14-95  rst / rh
  74.  *      Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
  75.  *      Apache server, and also to have child processes do accept() directly.
  76.  *
  77.  * April-July '95 rst
  78.  *      Extensive rework for Apache.
  79.  */
  80.  
  81. #ifndef SHARED_CORE_BOOTSTRAP
  82. #ifndef SHARED_CORE_TIESTATIC
  83.  
  84. #ifdef SHARED_CORE
  85. #define REALMAIN ap_main
  86. int ap_main(int argc, char *argv[]);
  87. #else
  88. #define REALMAIN main
  89. #endif
  90.  
  91. #define CORE_PRIVATE
  92.  
  93. #include "httpd.h"
  94. #include "http_main.h"
  95. #include "http_log.h"
  96. #include "http_config.h"    /* for read_config */
  97. #include "http_protocol.h"    /* for read_request */
  98. #include "http_request.h"    /* for process_request */
  99. #include "http_conf_globals.h"
  100. #include "http_core.h"        /* for get_remote_host */
  101. #include "http_vhost.h"
  102. #include "util_script.h"    /* to force util_script.c linking */
  103. #include "util_uri.h"
  104. #include "scoreboard.h"
  105. #include "multithread.h"
  106. #include <sys/stat.h>
  107. #ifdef USE_SHMGET_SCOREBOARD
  108. #include <sys/types.h>
  109. #include <sys/ipc.h>
  110. #include <sys/shm.h>
  111. #endif
  112. #ifdef SecureWare
  113. #include <sys/security.h>
  114. #include <sys/audit.h>
  115. #include <prot.h>
  116. #endif
  117. #ifdef WIN32
  118. #include "../os/win32/getopt.h"
  119. #elif !defined(BEOS) && !defined(TPF)
  120. #include <netinet/tcp.h>
  121. #endif
  122.  
  123. #ifdef HAVE_BSTRING_H
  124. #include <bstring.h>        /* for IRIX, FD_SET calls bzero() */
  125. #endif
  126.  
  127. #ifdef MULTITHREAD
  128. /* special debug stuff -- PCS */
  129.  
  130. /* Set this non-zero if you are prepared to put up with more than one log entry per second */
  131. #define SEVERELY_VERBOSE        0
  132.  
  133.   /* APD1() to APD5() are macros to help us debug. They can either
  134.    * log to the screen or the error_log file. In release builds, these
  135.    * macros do nothing. In debug builds, they send messages at priority
  136.    * "debug" to the error log file, or if DEBUG_TO_CONSOLE is defined,
  137.    * to the console.
  138.    */
  139.  
  140. # ifdef _DEBUG
  141. #  ifndef DEBUG_TO_CONSOLE
  142. #   define APD1(a) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a)
  143. #   define APD2(a,b) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b)
  144. #   define APD3(a,b,c) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c)
  145. #   define APD4(a,b,c,d) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c,d)
  146. #   define APD5(a,b,c,d,e) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c,d,e)
  147. #  else
  148. #   define APD1(a) printf("%s\n",a)
  149. #   define APD2(a,b) do { printf(a,b);putchar('\n'); } while(0);
  150. #   define APD3(a,b,c) do { printf(a,b,c);putchar('\n'); } while(0);
  151. #   define APD4(a,b,c,d) do { printf(a,b,c,d);putchar('\n'); } while(0);
  152. #   define APD5(a,b,c,d,e) do { printf(a,b,c,d,e);putchar('\n'); } while(0);
  153. #  endif
  154. # else /* !_DEBUG */
  155. #  define APD1(a) 
  156. #  define APD2(a,b) 
  157. #  define APD3(a,b,c) 
  158. #  define APD4(a,b,c,d) 
  159. #  define APD5(a,b,c,d,e) 
  160. # endif /* _DEBUG */
  161. #endif /* MULTITHREAD */
  162.  
  163. /* This next function is never used. It is here to ensure that if we
  164.  * make all the modules into shared libraries that core httpd still
  165.  * includes the full Apache API. Without this function the objects in
  166.  * main/util_script.c would not be linked into a minimal httpd.
  167.  * And the extra prototype is to make gcc -Wmissing-prototypes quiet.
  168.  */
  169. extern void ap_force_library_loading(void);
  170. void ap_force_library_loading(void) {
  171.     ap_add_cgi_vars(NULL);
  172. }
  173.  
  174. #include "explain.h"
  175.  
  176. #if !defined(max)
  177. #define max(a,b)        (a > b ? a : b)
  178. #endif
  179.  
  180. #ifdef WIN32
  181. #include "../os/win32/service.h"
  182. #include "../os/win32/registry.h"
  183. #endif
  184.  
  185.  
  186. #ifdef MINT
  187. long _stksize = 32768;
  188. #endif
  189.  
  190. #ifdef USE_OS2_SCOREBOARD
  191.     /* Add MMAP style functionality to OS/2 */
  192. #define INCL_DOSMEMMGR
  193. #define INCL_DOSEXCEPTIONS
  194. #define INCL_DOSSEMAPHORES
  195. #include <os2.h>
  196. #include <umalloc.h>
  197. #include <stdio.h>
  198. caddr_t create_shared_heap(const char *, size_t);
  199. caddr_t get_shared_heap(const char *);
  200. #endif
  201.  
  202. DEF_Explain
  203.  
  204. /* Defining GPROF when compiling uses the moncontrol() function to
  205.  * disable gprof profiling in the parent, and enable it only for
  206.  * request processing in children (or in one_process mode).  It's
  207.  * absolutely required to get useful gprof results under linux
  208.  * because the profile itimers and such are disabled across a
  209.  * fork().  It's probably useful elsewhere as well.
  210.  */
  211. #ifdef GPROF
  212. extern void moncontrol(int);
  213. #define MONCONTROL(x) moncontrol(x)
  214. #else
  215. #define MONCONTROL(x)
  216. #endif
  217.  
  218. #ifndef MULTITHREAD
  219. /* this just need to be anything non-NULL */
  220. void *ap_dummy_mutex = &ap_dummy_mutex;
  221. #endif
  222.  
  223. /*
  224.  * Actual definitions of config globals... here because this is
  225.  * for the most part the only code that acts on 'em.  (Hmmm... mod_main.c?)
  226.  */
  227.  
  228. int ap_standalone;
  229. uid_t ap_user_id;
  230. char *ap_user_name;
  231. gid_t ap_group_id;
  232. #ifdef MULTIPLE_GROUPS
  233. gid_t group_id_list[NGROUPS_MAX];
  234. #endif
  235. int ap_max_requests_per_child;
  236. int ap_threads_per_child;
  237. int ap_excess_requests_per_child;
  238. char *ap_pid_fname;
  239. char *ap_scoreboard_fname;
  240. char *ap_lock_fname;
  241. char *ap_server_argv0;
  242. struct in_addr ap_bind_address;
  243. int ap_daemons_to_start;
  244. int ap_daemons_min_free;
  245. int ap_daemons_max_free;
  246. int ap_daemons_limit;
  247. time_t ap_restart_time;
  248. int ap_suexec_enabled = 0;
  249. int ap_listenbacklog;
  250. int ap_dump_settings = 0;
  251. API_VAR_EXPORT int ap_extended_status = 0;
  252.  
  253. /*
  254.  * The max child slot ever assigned, preserved across restarts.  Necessary
  255.  * to deal with MaxClients changes across SIGUSR1 restarts.  We use this
  256.  * value to optimize routines that have to scan the entire scoreboard.
  257.  */
  258. static int max_daemons_limit = -1;
  259.  
  260. /*
  261.  * During config time, listeners is treated as a NULL-terminated list.
  262.  * child_main previously would start at the beginning of the list each time
  263.  * through the loop, so a socket early on in the list could easily starve out
  264.  * sockets later on in the list.  The solution is to start at the listener
  265.  * after the last one processed.  But to do that fast/easily in child_main it's
  266.  * way more convenient for listeners to be a ring that loops back on itself.
  267.  * The routine setup_listeners() is called after config time to both open up
  268.  * the sockets and to turn the NULL-terminated list into a ring that loops back
  269.  * on itself.
  270.  *
  271.  * head_listener is used by each child to keep track of what they consider
  272.  * to be the "start" of the ring.  It is also set by make_child to ensure
  273.  * that new children also don't starve any sockets.
  274.  *
  275.  * Note that listeners != NULL is ensured by read_config().
  276.  */
  277. listen_rec *ap_listeners;
  278. static listen_rec *head_listener;
  279.  
  280. API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN];
  281. char ap_server_confname[MAX_STRING_LEN];
  282. char ap_coredump_dir[MAX_STRING_LEN];
  283.  
  284. array_header *ap_server_pre_read_config;
  285. array_header *ap_server_post_read_config;
  286. array_header *ap_server_config_defines;
  287.  
  288. /* *Non*-shared http_main globals... */
  289.  
  290. static server_rec *server_conf;
  291. static JMP_BUF APACHE_TLS jmpbuffer;
  292. static int sd;
  293. static fd_set listenfds;
  294. static int listenmaxfd;
  295. static pid_t pgrp;
  296.  
  297. /* one_process --- debugging mode variable; can be set from the command line
  298.  * with the -X flag.  If set, this gets you the child_main loop running
  299.  * in the process which originally started up (no detach, no make_child),
  300.  * which is a pretty nice debugging environment.  (You'll get a SIGHUP
  301.  * early in standalone_main; just continue through.  This is the server
  302.  * trying to kill off any child processes which it might have lying
  303.  * around --- Apache doesn't keep track of their pids, it just sends
  304.  * SIGHUP to the process group, ignoring it in the root process.
  305.  * Continue through and you'll be fine.).
  306.  */
  307.  
  308. static int one_process = 0;
  309.  
  310. /* set if timeouts are to be handled by the children and not by the parent.
  311.  * i.e. child_timeouts = !standalone || one_process.
  312.  */
  313. static int child_timeouts;
  314.  
  315. #ifdef DEBUG_SIGSTOP
  316. int raise_sigstop_flags;
  317. #endif
  318.  
  319. #ifndef NO_OTHER_CHILD
  320. /* used to maintain list of children which aren't part of the scoreboard */
  321. typedef struct other_child_rec other_child_rec;
  322. struct other_child_rec {
  323.     other_child_rec *next;
  324.     int pid;
  325.     void (*maintenance) (int, void *, ap_wait_t);
  326.     void *data;
  327.     int write_fd;
  328. };
  329. static other_child_rec *other_children;
  330. #endif
  331.  
  332. static pool *pconf;        /* Pool for config stuff */
  333. static pool *ptrans;        /* Pool for per-transaction stuff */
  334. static pool *pchild;        /* Pool for httpd child stuff */
  335. static pool *pcommands;    /* Pool for -C and -c switches */
  336.  
  337. static int APACHE_TLS my_pid;    /* it seems silly to call getpid all the time */
  338. #ifndef MULTITHREAD
  339. static int my_child_num;
  340. #endif
  341.  
  342. scoreboard *ap_scoreboard_image = NULL;
  343.  
  344. /*
  345.  * Pieces for managing the contents of the Server response header
  346.  * field.
  347.  */
  348. static char *server_version = NULL;
  349. static int version_locked = 0;
  350.  
  351. /* Global, alas, so http_core can talk to us */
  352. enum server_token_type ap_server_tokens = SrvTk_FULL;
  353.  
  354. /*
  355.  * This routine is called when the pconf pool is vacuumed.  It resets the
  356.  * server version string to a known value and [re]enables modifications
  357.  * (which are disabled by configuration completion). 
  358.  */
  359. static void reset_version(void *dummy)
  360. {
  361.     version_locked = 0;
  362.     ap_server_tokens = SrvTk_FULL;
  363.     server_version = NULL;
  364. }
  365.  
  366. API_EXPORT(const char *) ap_get_server_version(void)
  367. {
  368.     return (server_version ? server_version : SERVER_BASEVERSION);
  369. }
  370.  
  371. API_EXPORT(void) ap_add_version_component(const char *component)
  372. {
  373.     if (! version_locked) {
  374.         /*
  375.          * If the version string is null, register our cleanup to reset the
  376.          * pointer on pool destruction. We also know that, if NULL,
  377.      * we are adding the original SERVER_BASEVERSION string.
  378.          */
  379.         if (server_version == NULL) {
  380.         ap_register_cleanup(pconf, NULL, (void (*)(void *))reset_version, 
  381.                 ap_null_cleanup);
  382.         server_version = ap_pstrdup(pconf, component);
  383.     }
  384.     else {
  385.         /*
  386.          * Tack the given component identifier to the end of
  387.          * the existing string.
  388.          */
  389.         server_version = ap_pstrcat(pconf, server_version, " ",
  390.                     component, NULL);
  391.     }
  392.     }
  393. }
  394.  
  395. /*
  396.  * This routine adds the real server base identity to the version string,
  397.  * and then locks out changes until the next reconfig.
  398.  */
  399. static void ap_set_version(void)
  400. {
  401.     if (ap_server_tokens == SrvTk_MIN) {
  402.     ap_add_version_component(SERVER_BASEVERSION);
  403.     }
  404.     else {
  405.     ap_add_version_component(SERVER_BASEVERSION " (" PLATFORM ")");
  406.     }
  407.     /*
  408.      * Lock the server_version string if we're not displaying
  409.      * the full set of tokens
  410.      */
  411.     if (ap_server_tokens != SrvTk_FULL) {
  412.     version_locked++;
  413.     }
  414. }
  415.  
  416. static APACHE_TLS int volatile exit_after_unblock = 0;
  417.  
  418. #ifdef GPROF
  419. /* 
  420.  * change directory for gprof to plop the gmon.out file
  421.  * configure in httpd.conf:
  422.  * GprofDir logs/   -> $ServerRoot/logs/gmon.out
  423.  * GprofDir logs/%  -> $ServerRoot/logs/gprof.$pid/gmon.out
  424.  */
  425. static void chdir_for_gprof(void)
  426. {
  427.     core_server_config *sconf = 
  428.     ap_get_module_config(server_conf->module_config, &core_module);    
  429.     char *dir = sconf->gprof_dir;
  430.  
  431.     if(dir) {
  432.     char buf[512];
  433.     int len = strlen(sconf->gprof_dir) - 1;
  434.     if(*(dir + len) == '%') {
  435.         dir[len] = '\0';
  436.         ap_snprintf(buf, sizeof(buf), "%sgprof.%d", dir, (int)getpid());
  437.     } 
  438.     dir = ap_server_root_relative(pconf, buf[0] ? buf : dir);
  439.     if(mkdir(dir, 0755) < 0 && errno != EEXIST) {
  440.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  441.              "gprof: error creating directory %s", dir);
  442.     }
  443.     }
  444.     else {
  445.     dir = ap_server_root_relative(pconf, "logs");
  446.     }
  447.  
  448.     chdir(dir);
  449. }
  450. #else
  451. #define chdir_for_gprof()
  452. #endif
  453.  
  454. /* a clean exit from a child with proper cleanup */
  455. static void clean_child_exit(int code) __attribute__ ((noreturn));
  456. static void clean_child_exit(int code)
  457. {
  458.     if (pchild) {
  459.     ap_child_exit_modules(pchild, server_conf);
  460.     ap_destroy_pool(pchild);
  461.     }
  462.     chdir_for_gprof();
  463.     exit(code);
  464. }
  465.  
  466. #if defined(USE_FCNTL_SERIALIZED_ACCEPT) || defined(USE_FLOCK_SERIALIZED_ACCEPT)
  467. static void expand_lock_fname(pool *p)
  468. {
  469.     /* XXXX possibly bogus cast */
  470.     ap_lock_fname = ap_psprintf(p, "%s.%lu",
  471.     ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid());
  472. }
  473. #endif
  474.  
  475. #if defined (USE_USLOCK_SERIALIZED_ACCEPT)
  476.  
  477. #include <ulocks.h>
  478.  
  479. static ulock_t uslock = NULL;
  480.  
  481. #define accept_mutex_child_init(x)
  482.  
  483. static void accept_mutex_init(pool *p)
  484. {
  485.     ptrdiff_t old;
  486.     usptr_t *us;
  487.  
  488.  
  489.     /* default is 8, allocate enough for all the children plus the parent */
  490.     if ((old = usconfig(CONF_INITUSERS, HARD_SERVER_LIMIT + 1)) == -1) {
  491.     perror("usconfig(CONF_INITUSERS)");
  492.     exit(-1);
  493.     }
  494.  
  495.     if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) {
  496.     perror("usconfig(CONF_LOCKTYPE)");
  497.     exit(-1);
  498.     }
  499.     if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) {
  500.     perror("usconfig(CONF_ARENATYPE)");
  501.     exit(-1);
  502.     }
  503.     if ((us = usinit("/dev/zero")) == NULL) {
  504.     perror("usinit");
  505.     exit(-1);
  506.     }
  507.  
  508.     if ((uslock = usnewlock(us)) == NULL) {
  509.     perror("usnewlock");
  510.     exit(-1);
  511.     }
  512. }
  513.  
  514. static void accept_mutex_on(void)
  515. {
  516.     switch (ussetlock(uslock)) {
  517.     case 1:
  518.     /* got lock */
  519.     break;
  520.     case 0:
  521.     fprintf(stderr, "didn't get lock\n");
  522.     clean_child_exit(APEXIT_CHILDFATAL);
  523.     case -1:
  524.     perror("ussetlock");
  525.     clean_child_exit(APEXIT_CHILDFATAL);
  526.     }
  527. }
  528.  
  529. static void accept_mutex_off(void)
  530. {
  531.     if (usunsetlock(uslock) == -1) {
  532.     perror("usunsetlock");
  533.     clean_child_exit(APEXIT_CHILDFATAL);
  534.     }
  535. }
  536.  
  537. #elif defined (USE_PTHREAD_SERIALIZED_ACCEPT)
  538.  
  539. /* This code probably only works on Solaris ... but it works really fast
  540.  * on Solaris.  Note that pthread mutexes are *NOT* released when a task
  541.  * dies ... the task has to free it itself.  So we block signals and
  542.  * try to be nice about releasing the mutex.
  543.  */
  544.  
  545. #include <pthread.h>
  546.  
  547. static pthread_mutex_t *accept_mutex = (void *)(caddr_t) -1;
  548. static int have_accept_mutex;
  549. static sigset_t accept_block_mask;
  550. static sigset_t accept_previous_mask;
  551.  
  552. static void accept_mutex_child_cleanup(void *foo)
  553. {
  554.     if (accept_mutex != (void *)(caddr_t)-1
  555.     && have_accept_mutex) {
  556.     pthread_mutex_unlock(accept_mutex);
  557.     }
  558. }
  559.  
  560. static void accept_mutex_child_init(pool *p)
  561. {
  562.     ap_register_cleanup(p, NULL, accept_mutex_child_cleanup, ap_null_cleanup);
  563. }
  564.  
  565. static void accept_mutex_cleanup(void *foo)
  566. {
  567.     if (accept_mutex != (void *)(caddr_t)-1
  568.     && munmap((caddr_t) accept_mutex, sizeof(*accept_mutex))) {
  569.     perror("munmap");
  570.     }
  571.     accept_mutex = (void *)(caddr_t)-1;
  572. }
  573.  
  574. static void accept_mutex_init(pool *p)
  575. {
  576.     pthread_mutexattr_t mattr;
  577.     int fd;
  578.  
  579.     fd = open("/dev/zero", O_RDWR);
  580.     if (fd == -1) {
  581.     perror("open(/dev/zero)");
  582.     exit(APEXIT_INIT);
  583.     }
  584.     accept_mutex = (pthread_mutex_t *) mmap((caddr_t) 0, sizeof(*accept_mutex),
  585.                  PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  586.     if (accept_mutex == (void *) (caddr_t) - 1) {
  587.     perror("mmap");
  588.     exit(APEXIT_INIT);
  589.     }
  590.     close(fd);
  591.     if ((errno = pthread_mutexattr_init(&mattr))) {
  592.     perror("pthread_mutexattr_init");
  593.     exit(APEXIT_INIT);
  594.     }
  595.     if ((errno = pthread_mutexattr_setpshared(&mattr,
  596.                         PTHREAD_PROCESS_SHARED))) {
  597.     perror("pthread_mutexattr_setpshared");
  598.     exit(APEXIT_INIT);
  599.     }
  600.     if ((errno = pthread_mutex_init(accept_mutex, &mattr))) {
  601.     perror("pthread_mutex_init");
  602.     exit(APEXIT_INIT);
  603.     }
  604.     sigfillset(&accept_block_mask);
  605.     sigdelset(&accept_block_mask, SIGHUP);
  606.     sigdelset(&accept_block_mask, SIGTERM);
  607.     sigdelset(&accept_block_mask, SIGUSR1);
  608.     ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
  609. }
  610.  
  611. static void accept_mutex_on(void)
  612. {
  613.     int err;
  614.  
  615.     if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
  616.     perror("sigprocmask(SIG_BLOCK)");
  617.     clean_child_exit(APEXIT_CHILDFATAL);
  618.     }
  619.     if ((err = pthread_mutex_lock(accept_mutex))) {
  620.     errno = err;
  621.     perror("pthread_mutex_lock");
  622.     clean_child_exit(APEXIT_CHILDFATAL);
  623.     }
  624.     have_accept_mutex = 1;
  625. }
  626.  
  627. static void accept_mutex_off(void)
  628. {
  629.     int err;
  630.  
  631.     if ((err = pthread_mutex_unlock(accept_mutex))) {
  632.     errno = err;
  633.     perror("pthread_mutex_unlock");
  634.     clean_child_exit(APEXIT_CHILDFATAL);
  635.     }
  636.     /* There is a slight race condition right here... if we were to die right
  637.      * now, we'd do another pthread_mutex_unlock.  Now, doing that would let
  638.      * another process into the mutex.  pthread mutexes are designed to be
  639.      * fast, as such they don't have protection for things like testing if the
  640.      * thread owning a mutex is actually unlocking it (or even any way of
  641.      * testing who owns the mutex).
  642.      *
  643.      * If we were to unset have_accept_mutex prior to releasing the mutex
  644.      * then the race could result in the server unable to serve hits.  Doing
  645.      * it this way means that the server can continue, but an additional
  646.      * child might be in the critical section ... at least it's still serving
  647.      * hits.
  648.      */
  649.     have_accept_mutex = 0;
  650.     if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
  651.     perror("sigprocmask(SIG_SETMASK)");
  652.     clean_child_exit(1);
  653.     }
  654. }
  655.  
  656. #elif defined (USE_SYSVSEM_SERIALIZED_ACCEPT)
  657.  
  658. #include <sys/types.h>
  659. #include <sys/ipc.h>
  660. #include <sys/sem.h>
  661.  
  662. #ifdef NEED_UNION_SEMUN
  663. /* it makes no sense, but this isn't defined on solaris */
  664. union semun {
  665.     long val;
  666.     struct semid_ds *buf;
  667.     ushort *array;
  668. };
  669.  
  670. #endif
  671.  
  672. static int sem_id = -1;
  673. static struct sembuf op_on;
  674. static struct sembuf op_off;
  675.  
  676. /* We get a random semaphore ... the lame sysv semaphore interface
  677.  * means we have to be sure to clean this up or else we'll leak
  678.  * semaphores.
  679.  */
  680. static void accept_mutex_cleanup(void *foo)
  681. {
  682.     union semun ick;
  683.  
  684.     if (sem_id < 0)
  685.     return;
  686.     /* this is ignored anyhow */
  687.     ick.val = 0;
  688.     semctl(sem_id, 0, IPC_RMID, ick);
  689. }
  690.  
  691. #define accept_mutex_child_init(x)
  692.  
  693. static void accept_mutex_init(pool *p)
  694. {
  695.     union semun ick;
  696.     struct semid_ds buf;
  697.  
  698.     /* acquire the semaphore */
  699.     sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
  700.     if (sem_id < 0) {
  701.     perror("semget");
  702.     exit(APEXIT_INIT);
  703.     }
  704.     ick.val = 1;
  705.     if (semctl(sem_id, 0, SETVAL, ick) < 0) {
  706.     perror("semctl(SETVAL)");
  707.     exit(APEXIT_INIT);
  708.     }
  709.     if (!getuid()) {
  710.     /* restrict it to use only by the appropriate user_id ... not that this
  711.      * stops CGIs from acquiring it and dinking around with it.
  712.      */
  713.     buf.sem_perm.uid = ap_user_id;
  714.     buf.sem_perm.gid = ap_group_id;
  715.     buf.sem_perm.mode = 0600;
  716.     ick.buf = &buf;
  717.     if (semctl(sem_id, 0, IPC_SET, ick) < 0) {
  718.         perror("semctl(IPC_SET)");
  719.         exit(APEXIT_INIT);
  720.     }
  721.     }
  722.     ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
  723.  
  724.     /* pre-initialize these */
  725.     op_on.sem_num = 0;
  726.     op_on.sem_op = -1;
  727.     op_on.sem_flg = SEM_UNDO;
  728.     op_off.sem_num = 0;
  729.     op_off.sem_op = 1;
  730.     op_off.sem_flg = SEM_UNDO;
  731. }
  732.  
  733. static void accept_mutex_on(void)
  734. {
  735.     if (semop(sem_id, &op_on, 1) < 0) {
  736.     perror("accept_mutex_on");
  737.     clean_child_exit(APEXIT_CHILDFATAL);
  738.     }
  739. }
  740.  
  741. static void accept_mutex_off(void)
  742. {
  743.     if (semop(sem_id, &op_off, 1) < 0) {
  744.     perror("accept_mutex_off");
  745.     clean_child_exit(APEXIT_CHILDFATAL);
  746.     }
  747. }
  748.  
  749. #elif defined(USE_FCNTL_SERIALIZED_ACCEPT)
  750. static struct flock lock_it;
  751. static struct flock unlock_it;
  752.  
  753. static int lock_fd = -1;
  754.  
  755. #define accept_mutex_child_init(x)
  756.  
  757. /*
  758.  * Initialize mutex lock.
  759.  * Must be safe to call this on a restart.
  760.  */
  761. static void accept_mutex_init(pool *p)
  762. {
  763.  
  764.     lock_it.l_whence = SEEK_SET;    /* from current point */
  765.     lock_it.l_start = 0;        /* -"- */
  766.     lock_it.l_len = 0;            /* until end of file */
  767.     lock_it.l_type = F_WRLCK;        /* set exclusive/write lock */
  768.     lock_it.l_pid = 0;            /* pid not actually interesting */
  769.     unlock_it.l_whence = SEEK_SET;    /* from current point */
  770.     unlock_it.l_start = 0;        /* -"- */
  771.     unlock_it.l_len = 0;        /* until end of file */
  772.     unlock_it.l_type = F_UNLCK;        /* set exclusive/write lock */
  773.     unlock_it.l_pid = 0;        /* pid not actually interesting */
  774.  
  775.     expand_lock_fname(p);
  776.     lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644);
  777.     if (lock_fd == -1) {
  778.     perror("open");
  779.     fprintf(stderr, "Cannot open lock file: %s\n", ap_lock_fname);
  780.     exit(APEXIT_INIT);
  781.     }
  782.     unlink(ap_lock_fname);
  783. }
  784.  
  785. static void accept_mutex_on(void)
  786. {
  787.     int ret;
  788.  
  789.     while ((ret = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR) {
  790.     /* nop */
  791.     }
  792.  
  793.     if (ret < 0) {
  794.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  795.             "fcntl: F_SETLKW: Error getting accept lock, exiting!  "
  796.             "Perhaps you need to use the LockFile directive to place "
  797.             "your lock file on a local disk!");
  798.     clean_child_exit(APEXIT_CHILDFATAL);
  799.     }
  800. }
  801.  
  802. static void accept_mutex_off(void)
  803. {
  804.     int ret;
  805.  
  806.     while ((ret = fcntl(lock_fd, F_SETLKW, &unlock_it)) < 0 && errno == EINTR) {
  807.     /* nop */
  808.     }
  809.     if (ret < 0) {
  810.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  811.             "fcntl: F_SETLKW: Error freeing accept lock, exiting!  "
  812.             "Perhaps you need to use the LockFile directive to place "
  813.             "your lock file on a local disk!");
  814.     clean_child_exit(APEXIT_CHILDFATAL);
  815.     }
  816. }
  817.  
  818. #elif defined(USE_FLOCK_SERIALIZED_ACCEPT)
  819.  
  820. static int lock_fd = -1;
  821.  
  822. static void accept_mutex_cleanup(void *foo)
  823. {
  824.     unlink(ap_lock_fname);
  825. }
  826.  
  827. /*
  828.  * Initialize mutex lock.
  829.  * Done by each child at it's birth
  830.  */
  831. static void accept_mutex_child_init(pool *p)
  832. {
  833.  
  834.     lock_fd = ap_popenf(p, ap_lock_fname, O_WRONLY, 0600);
  835.     if (lock_fd == -1) {
  836.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  837.             "Child cannot open lock file: %s", ap_lock_fname);
  838.     clean_child_exit(APEXIT_CHILDINIT);
  839.     }
  840. }
  841.  
  842. /*
  843.  * Initialize mutex lock.
  844.  * Must be safe to call this on a restart.
  845.  */
  846. static void accept_mutex_init(pool *p)
  847. {
  848.     expand_lock_fname(p);
  849.     unlink(ap_lock_fname);
  850.     lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600);
  851.     if (lock_fd == -1) {
  852.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  853.             "Parent cannot open lock file: %s", ap_lock_fname);
  854.     exit(APEXIT_INIT);
  855.     }
  856.     ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
  857. }
  858.  
  859. static void accept_mutex_on(void)
  860. {
  861.     int ret;
  862.  
  863.     while ((ret = flock(lock_fd, LOCK_EX)) < 0 && errno == EINTR)
  864.     continue;
  865.  
  866.     if (ret < 0) {
  867.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  868.             "flock: LOCK_EX: Error getting accept lock. Exiting!");
  869.     clean_child_exit(APEXIT_CHILDFATAL);
  870.     }
  871. }
  872.  
  873. static void accept_mutex_off(void)
  874. {
  875.     if (flock(lock_fd, LOCK_UN) < 0) {
  876.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  877.             "flock: LOCK_UN: Error freeing accept lock. Exiting!");
  878.     clean_child_exit(APEXIT_CHILDFATAL);
  879.     }
  880. }
  881.  
  882. #elif defined(USE_OS2SEM_SERIALIZED_ACCEPT)
  883.  
  884. static HMTX lock_sem = -1;
  885.  
  886. static void accept_mutex_cleanup(void *foo)
  887. {
  888.     DosReleaseMutexSem(lock_sem);
  889.     DosCloseMutexSem(lock_sem);
  890. }
  891.  
  892. /*
  893.  * Initialize mutex lock.
  894.  * Done by each child at it's birth
  895.  */
  896. static void accept_mutex_child_init(pool *p)
  897. {
  898.     int rc = DosOpenMutexSem(NULL, &lock_sem);
  899.  
  900.     if (rc != 0) {
  901.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  902.             "Child cannot open lock semaphore");
  903.     clean_child_exit(APEXIT_CHILDINIT);
  904.     }
  905. }
  906.  
  907. /*
  908.  * Initialize mutex lock.
  909.  * Must be safe to call this on a restart.
  910.  */
  911. static void accept_mutex_init(pool *p)
  912. {
  913.     int rc = DosCreateMutexSem(NULL, &lock_sem, DC_SEM_SHARED, FALSE);
  914.  
  915.     if (rc != 0) {
  916.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  917.             "Parent cannot create lock semaphore");
  918.     exit(APEXIT_INIT);
  919.     }
  920.  
  921.     ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
  922. }
  923.  
  924. static void accept_mutex_on(void)
  925. {
  926.     int rc = DosRequestMutexSem(lock_sem, SEM_INDEFINITE_WAIT);
  927.  
  928.     if (rc != 0) {
  929.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  930.             "OS2SEM: Error %d getting accept lock. Exiting!", rc);
  931.     clean_child_exit(APEXIT_CHILDFATAL);
  932.     }
  933. }
  934.  
  935. static void accept_mutex_off(void)
  936. {
  937.     int rc = DosReleaseMutexSem(lock_sem);
  938.     
  939.     if (rc != 0) {
  940.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  941.             "OS2SEM: Error %d freeing accept lock. Exiting!", rc);
  942.     clean_child_exit(APEXIT_CHILDFATAL);
  943.     }
  944. }
  945.  
  946. #else
  947. /* Default --- no serialization.  Other methods *could* go here,
  948.  * as #elifs...
  949.  */
  950. #if !defined(MULTITHREAD)
  951. /* Multithreaded systems don't complete between processes for
  952.  * the sockets. */
  953. #define NO_SERIALIZED_ACCEPT
  954. #define accept_mutex_child_init(x)
  955. #define accept_mutex_init(x)
  956. #define accept_mutex_on()
  957. #define accept_mutex_off()
  958. #endif
  959. #endif
  960.  
  961. /* On some architectures it's safe to do unserialized accept()s in the single
  962.  * Listen case.  But it's never safe to do it in the case where there's
  963.  * multiple Listen statements.  Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
  964.  * when it's safe in the single Listen case.
  965.  */
  966. #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
  967. #define SAFE_ACCEPT(stmt) do {if(ap_listeners->next != ap_listeners) {stmt;}} while(0)
  968. #else
  969. #define SAFE_ACCEPT(stmt) do {stmt;} while(0)
  970. #endif
  971.  
  972. static void usage(char *bin)
  973. {
  974.     char pad[MAX_STRING_LEN];
  975.     unsigned i;
  976.  
  977.     for (i = 0; i < strlen(bin); i++)
  978.     pad[i] = ' ';
  979.     pad[i] = '\0';
  980. #ifdef SHARED_CORE
  981.     fprintf(stderr, "Usage: %s [-R directory] [-d directory] [-f file]\n", bin);
  982. #else
  983.     fprintf(stderr, "Usage: %s [-d directory] [-f file]\n", bin);
  984. #endif
  985.     fprintf(stderr, "       %s [-C \"directive\"] [-c \"directive\"]\n", pad);
  986.     fprintf(stderr, "       %s [-v] [-V] [-h] [-l] [-L] [-S] [-t]\n", pad);
  987.     fprintf(stderr, "Options:\n");
  988. #ifdef SHARED_CORE
  989.     fprintf(stderr, "  -R directory     : specify an alternate location for shared object files\n");
  990. #endif
  991.     fprintf(stderr, "  -D name          : define a name for use in <IfDefine name> directives\n");
  992.     fprintf(stderr, "  -d directory     : specify an alternate initial ServerRoot\n");
  993.     fprintf(stderr, "  -f file          : specify an alternate ServerConfigFile\n");
  994.     fprintf(stderr, "  -C \"directive\"   : process directive before reading config files\n");
  995.     fprintf(stderr, "  -c \"directive\"   : process directive after  reading config files\n");
  996.     fprintf(stderr, "  -v               : show version number\n");
  997.     fprintf(stderr, "  -V               : show compile settings\n");
  998.     fprintf(stderr, "  -h               : list available command line options (this page)\n");
  999.     fprintf(stderr, "  -l               : list compiled-in modules\n");
  1000.     fprintf(stderr, "  -L               : list available configuration directives\n");
  1001.     fprintf(stderr, "  -S               : show parsed settings (currently only vhost settings)\n");
  1002.     fprintf(stderr, "  -t               : run syntax test for configuration files only\n");
  1003. #ifdef WIN32
  1004.     fprintf(stderr, "  -k shutdown      : tell running Apache to shutdown\n");
  1005.     fprintf(stderr, "  -k restart       : tell running Apache to do a graceful restart\n");
  1006. #endif
  1007.     exit(1);
  1008. }
  1009.  
  1010. /*****************************************************************
  1011.  *
  1012.  * Timeout handling.  DISTINCTLY not thread-safe, but all this stuff
  1013.  * has to change for threads anyway.  Note that this code allows only
  1014.  * one timeout in progress at a time...
  1015.  */
  1016.  
  1017. static APACHE_TLS conn_rec *volatile current_conn;
  1018. static APACHE_TLS request_rec *volatile timeout_req;
  1019. static APACHE_TLS const char *volatile timeout_name = NULL;
  1020. static APACHE_TLS int volatile alarms_blocked = 0;
  1021. static APACHE_TLS int volatile alarm_pending = 0;
  1022.  
  1023. static void timeout(int sig)
  1024. {                /* Also called on SIGPIPE */
  1025.     void *dirconf;
  1026.  
  1027.     signal(SIGPIPE, SIG_IGN);    /* Block SIGPIPE */
  1028.     if (alarms_blocked) {
  1029.     alarm_pending = 1;
  1030.     return;
  1031.     }
  1032.     if (exit_after_unblock) {
  1033.     clean_child_exit(0);
  1034.     }
  1035.  
  1036.     if (!current_conn) {
  1037.     ap_longjmp(jmpbuffer, 1);
  1038.     }
  1039.  
  1040.     if (timeout_req != NULL)
  1041.     dirconf = timeout_req->per_dir_config;
  1042.     else
  1043.     dirconf = current_conn->server->lookup_defaults;
  1044.     if (!current_conn->keptalive) {
  1045.     if (sig == SIGPIPE) {
  1046.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
  1047.             current_conn->server,
  1048.             "[client %s] stopped connection before %s completed",
  1049.             current_conn->remote_ip,
  1050.             timeout_name ? timeout_name : "request");
  1051.     }
  1052.     else {
  1053.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
  1054.             current_conn->server,
  1055.             "[client %s] %s timed out",
  1056.             current_conn->remote_ip,
  1057.             timeout_name ? timeout_name : "request");
  1058.     }
  1059.     }
  1060.  
  1061.     if (timeout_req) {
  1062.     /* Someone has asked for this transaction to just be aborted
  1063.      * if it times out...
  1064.      */
  1065.  
  1066.     request_rec *log_req = timeout_req;
  1067.     request_rec *save_req = timeout_req;
  1068.  
  1069.     /* avoid looping... if ap_log_transaction started another
  1070.      * timer (say via rfc1413.c) we could loop...
  1071.      */
  1072.     timeout_req = NULL;
  1073.  
  1074.     while (log_req->main || log_req->prev) {
  1075.         /* Get back to original request... */
  1076.         if (log_req->main)
  1077.         log_req = log_req->main;
  1078.         else
  1079.         log_req = log_req->prev;
  1080.     }
  1081.  
  1082.     if (!current_conn->keptalive)
  1083.         ap_log_transaction(log_req);
  1084.  
  1085.     ap_bsetflag(save_req->connection->client, B_EOUT, 1);
  1086.     ap_bclose(save_req->connection->client);
  1087.  
  1088.     if (!ap_standalone)
  1089.         exit(0);
  1090.  
  1091.     ap_longjmp(jmpbuffer, 1);
  1092.     }
  1093.     else {            /* abort the connection */
  1094.     ap_bsetflag(current_conn->client, B_EOUT, 1);
  1095.     ap_bclose(current_conn->client);
  1096.     current_conn->aborted = 1;
  1097.     }
  1098. }
  1099.  
  1100. #ifndef TPF
  1101. /*
  1102.  * These two called from alloc.c to protect its critical sections...
  1103.  * Note that they can nest (as when destroying the sub_pools of a pool
  1104.  * which is itself being cleared); we have to support that here.
  1105.  */
  1106.  
  1107. API_EXPORT(void) ap_block_alarms(void)
  1108. {
  1109.     ++alarms_blocked;
  1110. }
  1111.  
  1112. API_EXPORT(void) ap_unblock_alarms(void)
  1113. {
  1114.     --alarms_blocked;
  1115.     if (alarms_blocked == 0) {
  1116.     if (exit_after_unblock) {
  1117.         /* We have a couple race conditions to deal with here, we can't
  1118.          * allow a timeout that comes in this small interval to allow
  1119.          * the child to jump back to the main loop.  Instead we block
  1120.          * alarms again, and then note that exit_after_unblock is
  1121.          * being dealt with.  We choose this way to solve this so that
  1122.          * the common path through unblock_alarms() is really short.
  1123.          */
  1124.         ++alarms_blocked;
  1125.         exit_after_unblock = 0;
  1126.         clean_child_exit(0);
  1127.     }
  1128.     if (alarm_pending) {
  1129.         alarm_pending = 0;
  1130.         timeout(0);
  1131.     }
  1132.     }
  1133. }
  1134. #endif /* TPF */
  1135.  
  1136. static APACHE_TLS void (*volatile alarm_fn) (int) = NULL;
  1137. #ifdef WIN32
  1138. static APACHE_TLS unsigned int alarm_expiry_time = 0;
  1139. #endif /* WIN32 */
  1140.  
  1141. #ifndef WIN32
  1142. static void alrm_handler(int sig)
  1143. {
  1144.     if (alarm_fn) {
  1145.     (*alarm_fn) (sig);
  1146.     }
  1147. }
  1148. #endif
  1149.  
  1150. unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x)
  1151. {
  1152.     unsigned int old;
  1153.  
  1154. #ifdef WIN32
  1155.     old = alarm_expiry_time;
  1156.     if (old)
  1157.     old -= time(0);
  1158.     if (x == 0) {
  1159.     alarm_fn = NULL;
  1160.     alarm_expiry_time = 0;
  1161.     }
  1162.     else {
  1163.     alarm_fn = fn;
  1164.     alarm_expiry_time = time(NULL) + x;
  1165.     }
  1166. #else
  1167.     if (alarm_fn && x && fn != alarm_fn) {
  1168.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, NULL,
  1169.         "ap_set_callback_and_alarm: possible nested timer!");
  1170.     }
  1171.     alarm_fn = fn;
  1172. #ifndef OPTIMIZE_TIMEOUTS
  1173.     old = alarm(x);
  1174. #else
  1175.     if (child_timeouts) {
  1176.     old = alarm(x);
  1177.     }
  1178.     else {
  1179.     /* Just note the timeout in our scoreboard, no need to call the system.
  1180.      * We also note that the virtual time has gone forward.
  1181.      */
  1182.     old = ap_scoreboard_image->servers[my_child_num].timeout_len;
  1183.     ap_scoreboard_image->servers[my_child_num].timeout_len = x;
  1184.     ++ap_scoreboard_image->servers[my_child_num].cur_vtime;
  1185.     }
  1186. #endif
  1187. #endif
  1188.     return (old);
  1189. }
  1190.  
  1191.  
  1192. #ifdef WIN32
  1193. API_EXPORT(int) ap_check_alarm(void)
  1194. {
  1195.     if (alarm_expiry_time) {
  1196.     unsigned int t;
  1197.  
  1198.     t = time(NULL);
  1199.     if (t >= alarm_expiry_time) {
  1200.         alarm_expiry_time = 0;
  1201.         (*alarm_fn) (0);
  1202.         return (-1);
  1203.     }
  1204.     else {
  1205.         return (alarm_expiry_time - t);
  1206.     }
  1207.     }
  1208.     else
  1209.     return (0);
  1210. }
  1211. #endif /* WIN32 */
  1212.  
  1213.  
  1214.  
  1215. /* reset_timeout (request_rec *) resets the timeout in effect,
  1216.  * as long as it hasn't expired already.
  1217.  */
  1218.  
  1219. API_EXPORT(void) ap_reset_timeout(request_rec *r)
  1220. {
  1221.     int i;
  1222.  
  1223.     if (timeout_name) {        /* timeout has been set */
  1224.     i = ap_set_callback_and_alarm(alarm_fn, r->server->timeout);
  1225.     if (i == 0)        /* timeout already expired, so set it back to 0 */
  1226.         ap_set_callback_and_alarm(alarm_fn, 0);
  1227.     }
  1228. }
  1229.  
  1230.  
  1231.  
  1232.  
  1233. void ap_keepalive_timeout(char *name, request_rec *r)
  1234. {
  1235.     unsigned int to;
  1236.  
  1237.     timeout_req = r;
  1238.     timeout_name = name;
  1239.  
  1240.     if (r->connection->keptalive)
  1241.     to = r->server->keep_alive_timeout;
  1242.     else
  1243.     to = r->server->timeout;
  1244.     ap_set_callback_and_alarm(timeout, to);
  1245.  
  1246. }
  1247.  
  1248. API_EXPORT(void) ap_hard_timeout(char *name, request_rec *r)
  1249. {
  1250.     timeout_req = r;
  1251.     timeout_name = name;
  1252.  
  1253.     ap_set_callback_and_alarm(timeout, r->server->timeout);
  1254.  
  1255. }
  1256.  
  1257. API_EXPORT(void) ap_soft_timeout(char *name, request_rec *r)
  1258. {
  1259.     timeout_name = name;
  1260.  
  1261.     ap_set_callback_and_alarm(timeout, r->server->timeout);
  1262.  
  1263. }
  1264.  
  1265. API_EXPORT(void) ap_kill_timeout(request_rec *dummy)
  1266. {
  1267.     ap_set_callback_and_alarm(NULL, 0);
  1268.     timeout_req = NULL;
  1269.     timeout_name = NULL;
  1270. }
  1271.  
  1272.  
  1273. /*
  1274.  * More machine-dependent networking gooo... on some systems,
  1275.  * you've got to be *really* sure that all the packets are acknowledged
  1276.  * before closing the connection, since the client will not be able
  1277.  * to see the last response if their TCP buffer is flushed by a RST
  1278.  * packet from us, which is what the server's TCP stack will send
  1279.  * if it receives any request data after closing the connection.
  1280.  *
  1281.  * In an ideal world, this function would be accomplished by simply
  1282.  * setting the socket option SO_LINGER and handling it within the
  1283.  * server's TCP stack while the process continues on to the next request.
  1284.  * Unfortunately, it seems that most (if not all) operating systems
  1285.  * block the server process on close() when SO_LINGER is used.
  1286.  * For those that don't, see USE_SO_LINGER below.  For the rest,
  1287.  * we have created a home-brew lingering_close.
  1288.  *
  1289.  * Many operating systems tend to block, puke, or otherwise mishandle
  1290.  * calls to shutdown only half of the connection.  You should define
  1291.  * NO_LINGCLOSE in ap_config.h if such is the case for your system.
  1292.  */
  1293. #ifndef MAX_SECS_TO_LINGER
  1294. #define MAX_SECS_TO_LINGER 30
  1295. #endif
  1296.  
  1297. #ifdef USE_SO_LINGER
  1298. #define NO_LINGCLOSE        /* The two lingering options are exclusive */
  1299.  
  1300. static void sock_enable_linger(int s)
  1301. {
  1302.     struct linger li;
  1303.  
  1304.     li.l_onoff = 1;
  1305.     li.l_linger = MAX_SECS_TO_LINGER;
  1306.  
  1307.     if (setsockopt(s, SOL_SOCKET, SO_LINGER,
  1308.            (char *) &li, sizeof(struct linger)) < 0) {
  1309.     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
  1310.                 "setsockopt: (SO_LINGER)");
  1311.     /* not a fatal error */
  1312.     }
  1313. }
  1314.  
  1315. #else
  1316. #define sock_enable_linger(s)    /* NOOP */
  1317. #endif /* USE_SO_LINGER */
  1318.  
  1319. #ifndef NO_LINGCLOSE
  1320.  
  1321. /* Special version of timeout for lingering_close */
  1322.  
  1323. static void lingerout(int sig)
  1324. {
  1325.     if (alarms_blocked) {
  1326.     alarm_pending = 1;
  1327.     return;
  1328.     }
  1329.  
  1330.     if (!current_conn) {
  1331.     ap_longjmp(jmpbuffer, 1);
  1332.     }
  1333.     ap_bsetflag(current_conn->client, B_EOUT, 1);
  1334.     current_conn->aborted = 1;
  1335. }
  1336.  
  1337. static void linger_timeout(void)
  1338. {
  1339.     timeout_name = "lingering close";
  1340.  
  1341.     ap_set_callback_and_alarm(lingerout, MAX_SECS_TO_LINGER);
  1342. }
  1343.  
  1344. /* Since many clients will abort a connection instead of closing it,
  1345.  * attempting to log an error message from this routine will only
  1346.  * confuse the webmaster.  There doesn't seem to be any portable way to
  1347.  * distinguish between a dropped connection and something that might be
  1348.  * worth logging.
  1349.  */
  1350. static void lingering_close(request_rec *r)
  1351. {
  1352.     char dummybuf[512];
  1353.     struct timeval tv;
  1354.     fd_set lfds;
  1355.     int select_rv;
  1356.     int lsd;
  1357.  
  1358.     /* Prevent a slow-drip client from holding us here indefinitely */
  1359.  
  1360.     linger_timeout();
  1361.  
  1362.     /* Send any leftover data to the client, but never try to again */
  1363.  
  1364.     if (ap_bflush(r->connection->client) == -1) {
  1365.     ap_kill_timeout(r);
  1366.     ap_bclose(r->connection->client);
  1367.     return;
  1368.     }
  1369.     ap_bsetflag(r->connection->client, B_EOUT, 1);
  1370.  
  1371.     /* Close our half of the connection --- send the client a FIN */
  1372.  
  1373.     lsd = r->connection->client->fd;
  1374.  
  1375.     if ((shutdown(lsd, 1) != 0) || r->connection->aborted) {
  1376.     ap_kill_timeout(r);
  1377.     ap_bclose(r->connection->client);
  1378.     return;
  1379.     }
  1380.  
  1381.     /* Set up to wait for readable data on socket... */
  1382.  
  1383.     FD_ZERO(&lfds);
  1384.  
  1385.     /* Wait for readable data or error condition on socket;
  1386.      * slurp up any data that arrives...  We exit when we go for an
  1387.      * interval of tv length without getting any more data, get an error
  1388.      * from select(), get an error or EOF on a read, or the timer expires.
  1389.      */
  1390.  
  1391.     do {
  1392.     /* We use a 2 second timeout because current (Feb 97) browsers
  1393.      * fail to close a connection after the server closes it.  Thus,
  1394.      * to avoid keeping the child busy, we are only lingering long enough
  1395.      * for a client that is actively sending data on a connection.
  1396.      * This should be sufficient unless the connection is massively
  1397.      * losing packets, in which case we might have missed the RST anyway.
  1398.      * These parameters are reset on each pass, since they might be
  1399.      * changed by select.
  1400.      */
  1401.     FD_SET(lsd, &lfds);
  1402.     tv.tv_sec = 2;
  1403.     tv.tv_usec = 0;
  1404.  
  1405.     select_rv = ap_select(lsd + 1, &lfds, NULL, NULL, &tv);
  1406.  
  1407.     } while ((select_rv > 0) &&
  1408.              (read(lsd, dummybuf, sizeof dummybuf) > 0));
  1409.  
  1410.     /* Should now have seen final ack.  Safe to finally kill socket */
  1411.  
  1412.     ap_bclose(r->connection->client);
  1413.  
  1414.     ap_kill_timeout(r);
  1415. }
  1416. #endif /* ndef NO_LINGCLOSE */
  1417.  
  1418. /*****************************************************************
  1419.  * dealing with other children
  1420.  */
  1421.  
  1422. #ifndef NO_OTHER_CHILD
  1423. API_EXPORT(void) ap_register_other_child(int pid,
  1424.                void (*maintenance) (int reason, void *, ap_wait_t status),
  1425.               void *data, int write_fd)
  1426. {
  1427.     other_child_rec *ocr;
  1428.  
  1429.     ocr = ap_palloc(pconf, sizeof(*ocr));
  1430.     ocr->pid = pid;
  1431.     ocr->maintenance = maintenance;
  1432.     ocr->data = data;
  1433.     ocr->write_fd = write_fd;
  1434.     ocr->next = other_children;
  1435.     other_children = ocr;
  1436. }
  1437.  
  1438. /* note that since this can be called by a maintenance function while we're
  1439.  * scanning the other_children list, all scanners should protect themself
  1440.  * by loading ocr->next before calling any maintenance function.
  1441.  */
  1442. API_EXPORT(void) ap_unregister_other_child(void *data)
  1443. {
  1444.     other_child_rec **pocr, *nocr;
  1445.  
  1446.     for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
  1447.     if ((*pocr)->data == data) {
  1448.         nocr = (*pocr)->next;
  1449.         (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, -1);
  1450.         *pocr = nocr;
  1451.         /* XXX: um, well we've just wasted some space in pconf ? */
  1452.         return;
  1453.     }
  1454.     }
  1455. }
  1456.  
  1457. /* test to ensure that the write_fds are all still writable, otherwise
  1458.  * invoke the maintenance functions as appropriate */
  1459. static void probe_writable_fds(void)
  1460. {
  1461.     fd_set writable_fds;
  1462.     int fd_max;
  1463.     other_child_rec *ocr, *nocr;
  1464.     struct timeval tv;
  1465.     int rc;
  1466.  
  1467.     if (other_children == NULL)
  1468.     return;
  1469.  
  1470.     fd_max = 0;
  1471.     FD_ZERO(&writable_fds);
  1472.     do {
  1473.     for (ocr = other_children; ocr; ocr = ocr->next) {
  1474.         if (ocr->write_fd == -1)
  1475.         continue;
  1476.         FD_SET(ocr->write_fd, &writable_fds);
  1477.         if (ocr->write_fd > fd_max) {
  1478.         fd_max = ocr->write_fd;
  1479.         }
  1480.     }
  1481.     if (fd_max == 0)
  1482.         return;
  1483.  
  1484.     tv.tv_sec = 0;
  1485.     tv.tv_usec = 0;
  1486.     rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
  1487.     } while (rc == -1 && errno == EINTR);
  1488.  
  1489.     if (rc == -1) {
  1490.     /* XXX: uhh this could be really bad, we could have a bad file
  1491.      * descriptor due to a bug in one of the maintenance routines */
  1492.     ap_log_unixerr("probe_writable_fds", "select",
  1493.             "could not probe writable fds", server_conf);
  1494.     return;
  1495.     }
  1496.     if (rc == 0)
  1497.     return;
  1498.  
  1499.     for (ocr = other_children; ocr; ocr = nocr) {
  1500.     nocr = ocr->next;
  1501.     if (ocr->write_fd == -1)
  1502.         continue;
  1503.     if (FD_ISSET(ocr->write_fd, &writable_fds))
  1504.         continue;
  1505.     (*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, -1);
  1506.     }
  1507. }
  1508.  
  1509. /* possibly reap an other_child, return 0 if yes, -1 if not */
  1510. static int reap_other_child(int pid, ap_wait_t status)
  1511. {
  1512.     other_child_rec *ocr, *nocr;
  1513.  
  1514.     for (ocr = other_children; ocr; ocr = nocr) {
  1515.     nocr = ocr->next;
  1516.     if (ocr->pid != pid)
  1517.         continue;
  1518.     ocr->pid = -1;
  1519.     (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
  1520.     return 0;
  1521.     }
  1522.     return -1;
  1523. }
  1524. #endif
  1525.  
  1526. /*****************************************************************
  1527.  *
  1528.  * Dealing with the scoreboard... a lot of these variables are global
  1529.  * only to avoid getting clobbered by the longjmp() that happens when
  1530.  * a hard timeout expires...
  1531.  *
  1532.  * We begin with routines which deal with the file itself... 
  1533.  */
  1534.  
  1535. #ifdef MULTITHREAD
  1536. /*
  1537.  * In the multithreaded mode, have multiple threads - not multiple
  1538.  * processes that need to talk to each other. Just use a simple
  1539.  * malloc. But let the routines that follow, think that you have
  1540.  * shared memory (so they use memcpy etc.)
  1541.  */
  1542.  
  1543. static void reinit_scoreboard(pool *p)
  1544. {
  1545.     ap_assert(!ap_scoreboard_image);
  1546.     ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
  1547.     memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
  1548. }
  1549.  
  1550. void cleanup_scoreboard(void)
  1551. {
  1552.     ap_assert(ap_scoreboard_image);
  1553.     free(ap_scoreboard_image);
  1554.     ap_scoreboard_image = NULL;
  1555. }
  1556.  
  1557. API_EXPORT(void) ap_sync_scoreboard_image(void)
  1558. {
  1559. }
  1560.  
  1561.  
  1562. #else /* MULTITHREAD */
  1563. #if defined(USE_OS2_SCOREBOARD)
  1564.  
  1565. /* The next two routines are used to access shared memory under OS/2.  */
  1566. /* This requires EMX v09c to be installed.                           */
  1567.  
  1568. caddr_t create_shared_heap(const char *name, size_t size)
  1569. {
  1570.     ULONG rc;
  1571.     void *mem;
  1572.     Heap_t h;
  1573.  
  1574.     rc = DosAllocSharedMem(&mem, name, size,
  1575.                PAG_COMMIT | PAG_READ | PAG_WRITE);
  1576.     if (rc != 0)
  1577.     return NULL;
  1578.     h = _ucreate(mem, size, !_BLOCK_CLEAN, _HEAP_REGULAR | _HEAP_SHARED,
  1579.          NULL, NULL);
  1580.     if (h == NULL)
  1581.     DosFreeMem(mem);
  1582.     return (caddr_t) h;
  1583. }
  1584.  
  1585. caddr_t get_shared_heap(const char *Name)
  1586. {
  1587.  
  1588.     PVOID BaseAddress;        /* Pointer to the base address of
  1589.                    the shared memory object */
  1590.     ULONG AttributeFlags;    /* Flags describing characteristics
  1591.                    of the shared memory object */
  1592.     APIRET rc;            /* Return code */
  1593.  
  1594.     /* Request read and write access to */
  1595.     /*   the shared memory object       */
  1596.     AttributeFlags = PAG_WRITE | PAG_READ;
  1597.  
  1598.     rc = DosGetNamedSharedMem(&BaseAddress, Name, AttributeFlags);
  1599.  
  1600.     if (rc != 0) {
  1601.     printf("DosGetNamedSharedMem error: return code = %ld", rc);
  1602.     return 0;
  1603.     }
  1604.  
  1605.     return BaseAddress;
  1606. }
  1607.  
  1608. static void setup_shared_mem(pool *p)
  1609. {
  1610.     caddr_t m;
  1611.  
  1612.     int rc;
  1613.  
  1614.     m = (caddr_t) create_shared_heap("\\SHAREMEM\\SCOREBOARD", SCOREBOARD_SIZE);
  1615.     if (m == 0) {
  1616.     fprintf(stderr, "%s: Could not create OS/2 Shared memory pool.\n",
  1617.         ap_server_argv0);
  1618.     exit(APEXIT_INIT);
  1619.     }
  1620.  
  1621.     rc = _uopen((Heap_t) m);
  1622.     if (rc != 0) {
  1623.     fprintf(stderr,
  1624.         "%s: Could not uopen() newly created OS/2 Shared memory pool.\n",
  1625.         ap_server_argv0);
  1626.     }
  1627.     ap_scoreboard_image = (scoreboard *) m;
  1628.     ap_scoreboard_image->global.running_generation = 0;
  1629. }
  1630.  
  1631. static void reopen_scoreboard(pool *p)
  1632. {
  1633.     caddr_t m;
  1634.     int rc;
  1635.  
  1636.     m = (caddr_t) get_shared_heap("\\SHAREMEM\\SCOREBOARD");
  1637.     if (m == 0) {
  1638.     fprintf(stderr, "%s: Could not find existing OS/2 Shared memory pool.\n",
  1639.         ap_server_argv0);
  1640.     exit(APEXIT_INIT);
  1641.     }
  1642.  
  1643.     rc = _uopen((Heap_t) m);
  1644.     ap_scoreboard_image = (scoreboard *) m;
  1645. }
  1646.  
  1647. #elif defined(USE_POSIX_SCOREBOARD)
  1648. #include <sys/mman.h>
  1649. /* 
  1650.  * POSIX 1003.4 style
  1651.  *
  1652.  * Note 1: 
  1653.  * As of version 4.23A, shared memory in QNX must reside under /dev/shmem,
  1654.  * where no subdirectories allowed.
  1655.  *
  1656.  * POSIX shm_open() and shm_unlink() will take care about this issue,
  1657.  * but to avoid confusion, I suggest to redefine scoreboard file name
  1658.  * in httpd.conf to cut "logs/" from it. With default setup actual name
  1659.  * will be "/dev/shmem/logs.apache_status". 
  1660.  * 
  1661.  * If something went wrong and Apache did not unlinked this object upon
  1662.  * exit, you can remove it manually, using "rm -f" command.
  1663.  * 
  1664.  * Note 2:
  1665.  * <sys/mman.h> in QNX defines MAP_ANON, but current implementation 
  1666.  * does NOT support BSD style anonymous mapping. So, the order of 
  1667.  * conditional compilation is important: 
  1668.  * this #ifdef section must be ABOVE the next one (BSD style).
  1669.  *
  1670.  * I tested this stuff and it works fine for me, but if it provides 
  1671.  * trouble for you, just comment out USE_MMAP_SCOREBOARD in QNX section
  1672.  * of ap_config.h
  1673.  *
  1674.  * June 5, 1997, 
  1675.  * Igor N. Kovalenko -- infoh@mail.wplus.net
  1676.  */
  1677.  
  1678. static void cleanup_shared_mem(void *d)
  1679. {
  1680.     shm_unlink(ap_scoreboard_fname);
  1681. }
  1682.  
  1683. static void setup_shared_mem(pool *p)
  1684. {
  1685.     char buf[512];
  1686.     caddr_t m;
  1687.     int fd;
  1688.  
  1689.     fd = shm_open(ap_scoreboard_fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  1690.     if (fd == -1) {
  1691.     ap_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
  1692.             ap_server_argv0);
  1693.     perror(buf);
  1694.     exit(APEXIT_INIT);
  1695.     }
  1696.     if (ltrunc(fd, (off_t) SCOREBOARD_SIZE, SEEK_SET) == -1) {
  1697.     ap_snprintf(buf, sizeof(buf), "%s: could not ltrunc scoreboard",
  1698.             ap_server_argv0);
  1699.     perror(buf);
  1700.     shm_unlink(ap_scoreboard_fname);
  1701.     exit(APEXIT_INIT);
  1702.     }
  1703.     if ((m = (caddr_t) mmap((caddr_t) 0,
  1704.                 (size_t) SCOREBOARD_SIZE, PROT_READ | PROT_WRITE,
  1705.                 MAP_SHARED, fd, (off_t) 0)) == (caddr_t) - 1) {
  1706.     ap_snprintf(buf, sizeof(buf), "%s: cannot mmap scoreboard",
  1707.             ap_server_argv0);
  1708.     perror(buf);
  1709.     shm_unlink(ap_scoreboard_fname);
  1710.     exit(APEXIT_INIT);
  1711.     }
  1712.     close(fd);
  1713.     ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup);
  1714.     ap_scoreboard_image = (scoreboard *) m;
  1715.     ap_scoreboard_image->global.running_generation = 0;
  1716. }
  1717.  
  1718. static void reopen_scoreboard(pool *p)
  1719. {
  1720. }
  1721.  
  1722. #elif defined(USE_MMAP_SCOREBOARD)
  1723.  
  1724. static void setup_shared_mem(pool *p)
  1725. {
  1726.     caddr_t m;
  1727.  
  1728. #if defined(MAP_ANON)
  1729. /* BSD style */
  1730. #ifdef CONVEXOS11
  1731.     /*
  1732.      * 9-Aug-97 - Jeff Venters (venters@convex.hp.com)
  1733.      * ConvexOS maps address space as follows:
  1734.      *   0x00000000 - 0x7fffffff : Kernel
  1735.      *   0x80000000 - 0xffffffff : User
  1736.      * Start mmapped area 1GB above start of text.
  1737.      *
  1738.      * Also, the length requires a pointer as the actual length is
  1739.      * returned (rounded up to a page boundary).
  1740.      */
  1741.     {
  1742.     unsigned len = SCOREBOARD_SIZE;
  1743.  
  1744.     m = mmap((caddr_t) 0xC0000000, &len,
  1745.          PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, NOFD, 0);
  1746.     }
  1747. #elif defined(MAP_TMPFILE)
  1748.     {
  1749.     char mfile[] = "/tmp/apache_shmem_XXXX";
  1750.     int fd = mkstemp(mfile);
  1751.     if (fd == -1) {
  1752.         perror("open");
  1753.         fprintf(stderr, "%s: Could not open %s\n", ap_server_argv0, mfile);
  1754.         exit(APEXIT_INIT);
  1755.     }
  1756.     m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
  1757.         PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  1758.     if (m == (caddr_t) - 1) {
  1759.         perror("mmap");
  1760.         fprintf(stderr, "%s: Could not mmap %s\n", ap_server_argv0, mfile);
  1761.         exit(APEXIT_INIT);
  1762.     }
  1763.     close(fd);
  1764.     unlink(mfile);
  1765.     }
  1766. #else
  1767.     m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
  1768.          PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
  1769. #endif
  1770.     if (m == (caddr_t) - 1) {
  1771.     perror("mmap");
  1772.     fprintf(stderr, "%s: Could not mmap memory\n", ap_server_argv0);
  1773.     exit(APEXIT_INIT);
  1774.     }
  1775. #else
  1776. /* Sun style */
  1777.     int fd;
  1778.  
  1779.     fd = open("/dev/zero", O_RDWR);
  1780.     if (fd == -1) {
  1781.     perror("open");
  1782.     fprintf(stderr, "%s: Could not open /dev/zero\n", ap_server_argv0);
  1783.     exit(APEXIT_INIT);
  1784.     }
  1785.     m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
  1786.          PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  1787.     if (m == (caddr_t) - 1) {
  1788.     perror("mmap");
  1789.     fprintf(stderr, "%s: Could not mmap /dev/zero\n", ap_server_argv0);
  1790.     exit(APEXIT_INIT);
  1791.     }
  1792.     close(fd);
  1793. #endif
  1794.     ap_scoreboard_image = (scoreboard *) m;
  1795.     ap_scoreboard_image->global.running_generation = 0;
  1796. }
  1797.  
  1798. static void reopen_scoreboard(pool *p)
  1799. {
  1800. }
  1801.  
  1802. #elif defined(USE_SHMGET_SCOREBOARD)
  1803. static key_t shmkey = IPC_PRIVATE;
  1804. static int shmid = -1;
  1805.  
  1806. static void setup_shared_mem(pool *p)
  1807. {
  1808.     struct shmid_ds shmbuf;
  1809. #ifdef MOVEBREAK
  1810.     char *obrk;
  1811. #endif
  1812.  
  1813.     if ((shmid = shmget(shmkey, SCOREBOARD_SIZE, IPC_CREAT | SHM_R | SHM_W)) == -1) {
  1814. #ifdef LINUX
  1815.     if (errno == ENOSYS) {
  1816.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
  1817.              "Your kernel was built without CONFIG_SYSVIPC\n"
  1818.              "%s: Please consult the Apache FAQ for details",
  1819.              ap_server_argv0);
  1820.     }
  1821. #endif
  1822.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  1823.             "could not call shmget");
  1824.     exit(APEXIT_INIT);
  1825.     }
  1826.  
  1827.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
  1828.         "created shared memory segment #%d", shmid);
  1829.  
  1830. #ifdef MOVEBREAK
  1831.     /*
  1832.      * Some SysV systems place the shared segment WAY too close
  1833.      * to the dynamic memory break point (sbrk(0)). This severely
  1834.      * limits the use of malloc/sbrk in the program since sbrk will
  1835.      * refuse to move past that point.
  1836.      *
  1837.      * To get around this, we move the break point "way up there",
  1838.      * attach the segment and then move break back down. Ugly
  1839.      */
  1840.     if ((obrk = sbrk(MOVEBREAK)) == (char *) -1) {
  1841.     ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  1842.         "sbrk() could not move break");
  1843.     }
  1844. #endif
  1845.  
  1846. #define BADSHMAT    ((scoreboard *)(-1))
  1847.     if ((ap_scoreboard_image = (scoreboard *) shmat(shmid, 0, 0)) == BADSHMAT) {
  1848.     ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "shmat error");
  1849.     /*
  1850.      * We exit below, after we try to remove the segment
  1851.      */
  1852.     }
  1853.     else {            /* only worry about permissions if we attached the segment */
  1854.     if (shmctl(shmid, IPC_STAT, &shmbuf) != 0) {
  1855.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  1856.         "shmctl() could not stat segment #%d", shmid);
  1857.     }
  1858.     else {
  1859.         shmbuf.shm_perm.uid = ap_user_id;
  1860.         shmbuf.shm_perm.gid = ap_group_id;
  1861.         if (shmctl(shmid, IPC_SET, &shmbuf) != 0) {
  1862.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  1863.             "shmctl() could not set segment #%d", shmid);
  1864.         }
  1865.     }
  1866.     }
  1867.     /*
  1868.      * We must avoid leaving segments in the kernel's
  1869.      * (small) tables.
  1870.      */
  1871.     if (shmctl(shmid, IPC_RMID, NULL) != 0) {
  1872.     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
  1873.         "shmctl: IPC_RMID: could not remove shared memory segment #%d",
  1874.         shmid);
  1875.     }
  1876.     if (ap_scoreboard_image == BADSHMAT)    /* now bailout */
  1877.     exit(APEXIT_INIT);
  1878.  
  1879. #ifdef MOVEBREAK
  1880.     if (obrk == (char *) -1)
  1881.     return;            /* nothing else to do */
  1882.     if (sbrk(-(MOVEBREAK)) == (char *) -1) {
  1883.     ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  1884.         "sbrk() could not move break back");
  1885.     }
  1886. #endif
  1887.     ap_scoreboard_image->global.running_generation = 0;
  1888. }
  1889.  
  1890. static void reopen_scoreboard(pool *p)
  1891. {
  1892. }
  1893.  
  1894. #else
  1895. #define SCOREBOARD_FILE
  1896. static scoreboard _scoreboard_image;
  1897. static int scoreboard_fd = -1;
  1898.  
  1899. /* XXX: things are seriously screwed if we ever have to do a partial
  1900.  * read or write ... we could get a corrupted scoreboard
  1901.  */
  1902. static int force_write(int fd, void *buffer, int bufsz)
  1903. {
  1904.     int rv, orig_sz = bufsz;
  1905.  
  1906.     do {
  1907.     rv = write(fd, buffer, bufsz);
  1908.     if (rv > 0) {
  1909.         buffer = (char *) buffer + rv;
  1910.         bufsz -= rv;
  1911.     }
  1912.     } while ((rv > 0 && bufsz > 0) || (rv == -1 && errno == EINTR));
  1913.  
  1914.     return rv < 0 ? rv : orig_sz - bufsz;
  1915. }
  1916.  
  1917. static int force_read(int fd, void *buffer, int bufsz)
  1918. {
  1919.     int rv, orig_sz = bufsz;
  1920.  
  1921.     do {
  1922.     rv = read(fd, buffer, bufsz);
  1923.     if (rv > 0) {
  1924.         buffer = (char *) buffer + rv;
  1925.         bufsz -= rv;
  1926.     }
  1927.     } while ((rv > 0 && bufsz > 0) || (rv == -1 && errno == EINTR));
  1928.  
  1929.     return rv < 0 ? rv : orig_sz - bufsz;
  1930. }
  1931.  
  1932. static void cleanup_scoreboard_file(void *foo)
  1933. {
  1934.     unlink(ap_scoreboard_fname);
  1935. }
  1936.  
  1937. void reopen_scoreboard(pool *p)
  1938. {
  1939.     if (scoreboard_fd != -1)
  1940.     ap_pclosef(p, scoreboard_fd);
  1941.  
  1942.     scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0666);
  1943.     if (scoreboard_fd == -1) {
  1944.     perror(ap_scoreboard_fname);
  1945.     fprintf(stderr, "Cannot open scoreboard file:\n");
  1946.     clean_child_exit(1);
  1947.     }
  1948. }
  1949. #endif
  1950.  
  1951. /* Called by parent process */
  1952. static void reinit_scoreboard(pool *p)
  1953. {
  1954.     int running_gen = 0;
  1955.     if (ap_scoreboard_image)
  1956.     running_gen = ap_scoreboard_image->global.running_generation;
  1957.  
  1958. #ifndef SCOREBOARD_FILE
  1959.     if (ap_scoreboard_image == NULL) {
  1960.     setup_shared_mem(p);
  1961.     }
  1962.     memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
  1963.     ap_scoreboard_image->global.running_generation = running_gen;
  1964. #else
  1965.     ap_scoreboard_image = &_scoreboard_image;
  1966.     ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
  1967.  
  1968.     scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0644);
  1969.     if (scoreboard_fd == -1) {
  1970.     perror(ap_scoreboard_fname);
  1971.     fprintf(stderr, "Cannot open scoreboard file:\n");
  1972.     exit(APEXIT_INIT);
  1973.     }
  1974.     ap_register_cleanup(p, NULL, cleanup_scoreboard_file, ap_null_cleanup);
  1975.  
  1976.     memset((char *) ap_scoreboard_image, 0, sizeof(*ap_scoreboard_image));
  1977.     ap_scoreboard_image->global.running_generation = running_gen;
  1978.     force_write(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
  1979. #endif
  1980. }
  1981.  
  1982. /* Routines called to deal with the scoreboard image
  1983.  * --- note that we do *not* need write locks, since update_child_status
  1984.  * only updates a *single* record in place, and only one process writes to
  1985.  * a given scoreboard slot at a time (either the child process owning that
  1986.  * slot, or the parent, noting that the child has died).
  1987.  *
  1988.  * As a final note --- setting the score entry to getpid() is always safe,
  1989.  * since when the parent is writing an entry, it's only noting SERVER_DEAD
  1990.  * anyway.
  1991.  */
  1992.  
  1993. ap_inline void ap_sync_scoreboard_image(void)
  1994. {
  1995. #ifdef SCOREBOARD_FILE
  1996.     lseek(scoreboard_fd, 0L, 0);
  1997.     force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
  1998. #endif
  1999. }
  2000.  
  2001. #endif /* MULTITHREAD */
  2002.  
  2003. API_EXPORT(int) ap_exists_scoreboard_image(void)
  2004. {
  2005.     return (ap_scoreboard_image ? 1 : 0);
  2006. }
  2007.  
  2008. static ap_inline void put_scoreboard_info(int child_num,
  2009.                        short_score *new_score_rec)
  2010. {
  2011. #ifdef SCOREBOARD_FILE
  2012.     lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
  2013.     force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
  2014. #endif
  2015. }
  2016.  
  2017. /* a clean exit from the parent with proper cleanup */
  2018. static void clean_parent_exit(int code) __attribute__((noreturn));
  2019. static void clean_parent_exit(int code)
  2020. {
  2021.     /* Clear the pool - including any registered cleanups */
  2022.     ap_destroy_pool(pconf);
  2023.     exit(code);
  2024. }
  2025.  
  2026. int ap_update_child_status(int child_num, int status, request_rec *r)
  2027. {
  2028.     int old_status;
  2029.     short_score *ss;
  2030.  
  2031.     if (child_num < 0)
  2032.     return -1;
  2033.  
  2034.     ap_sync_scoreboard_image();
  2035.     ss = &ap_scoreboard_image->servers[child_num];
  2036.     old_status = ss->status;
  2037.     ss->status = status;
  2038. #ifdef OPTIMIZE_TIMEOUTS
  2039.     ++ss->cur_vtime;
  2040. #endif
  2041.  
  2042.     if (ap_extended_status) {
  2043. #ifndef OPTIMIZE_TIMEOUTS
  2044.     ss->last_used = time(NULL);
  2045. #endif
  2046.     if (status == SERVER_READY || status == SERVER_DEAD) {
  2047.         /*
  2048.          * Reset individual counters
  2049.          */
  2050.         if (status == SERVER_DEAD) {
  2051.         ss->my_access_count = 0L;
  2052.         ss->my_bytes_served = 0L;
  2053.         }
  2054.         ss->conn_count = (unsigned short) 0;
  2055.         ss->conn_bytes = (unsigned long) 0;
  2056.     }
  2057.     if (r) {
  2058.         conn_rec *c = r->connection;
  2059.         ap_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
  2060.                   REMOTE_NOLOOKUP), sizeof(ss->client));
  2061.         if (r->the_request == NULL) {
  2062.             ap_cpystrn(ss->request, "NULL", sizeof(ss->request));
  2063.         } else if (r->parsed_uri.password == NULL) {
  2064.             ap_cpystrn(ss->request, r->the_request, sizeof(ss->request));
  2065.         } else {
  2066.         /* Don't reveal the password in the server-status view */
  2067.             ap_cpystrn(ss->request, ap_pstrcat(r->pool, r->method, " ",
  2068.                            ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
  2069.                            r->assbackwards ? NULL : " ", r->protocol, NULL),
  2070.                        sizeof(ss->request));
  2071.         }
  2072.         ss->vhostrec =  r->server;
  2073.     }
  2074.     }
  2075.     if (status == SERVER_STARTING && r == NULL) {
  2076.     /* clean up the slot's vhostrec pointer (maybe re-used)
  2077.      * and mark the slot as belonging to a new generation.
  2078.      */
  2079.     ss->vhostrec = NULL;
  2080.     ap_scoreboard_image->parent[child_num].generation = ap_my_generation;
  2081. #ifdef SCOREBOARD_FILE
  2082.     lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[child_num]), 0);
  2083.     force_write(scoreboard_fd, &ap_scoreboard_image->parent[child_num],
  2084.         sizeof(parent_score));
  2085. #endif
  2086.     }
  2087.     put_scoreboard_info(child_num, ss);
  2088.  
  2089.     return old_status;
  2090. }
  2091.  
  2092. static void update_scoreboard_global(void)
  2093. {
  2094. #ifdef SCOREBOARD_FILE
  2095.     lseek(scoreboard_fd,
  2096.       (char *) &ap_scoreboard_image->global -(char *) ap_scoreboard_image, 0);
  2097.     force_write(scoreboard_fd, &ap_scoreboard_image->global,
  2098.         sizeof ap_scoreboard_image->global);
  2099. #endif
  2100. }
  2101.  
  2102. void ap_time_process_request(int child_num, int status)
  2103. {
  2104.     short_score *ss;
  2105. #if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
  2106.     struct tms tms_blk;
  2107. #endif
  2108.  
  2109.     if (child_num < 0)
  2110.     return;
  2111.  
  2112.     ap_sync_scoreboard_image();
  2113.     ss = &ap_scoreboard_image->servers[child_num];
  2114.  
  2115.     if (status == START_PREQUEST) {
  2116. #if defined(NO_GETTIMEOFDAY)
  2117. #ifndef NO_TIMES
  2118.     if ((ss->start_time = times(&tms_blk)) == -1)
  2119. #endif /* NO_TIMES */
  2120.         ss->start_time = (clock_t) 0;
  2121. #else
  2122.     if (gettimeofday(&ss->start_time, (struct timezone *) 0) < 0)
  2123.         ss->start_time.tv_sec =
  2124.         ss->start_time.tv_usec = 0L;
  2125. #endif
  2126.     }
  2127.     else if (status == STOP_PREQUEST) {
  2128. #if defined(NO_GETTIMEOFDAY)
  2129. #ifndef NO_TIMES
  2130.     if ((ss->stop_time = times(&tms_blk)) == -1)
  2131. #endif
  2132.         ss->stop_time = ss->start_time = (clock_t) 0;
  2133. #else
  2134.     if (gettimeofday(&ss->stop_time, (struct timezone *) 0) < 0)
  2135.         ss->stop_time.tv_sec =
  2136.         ss->stop_time.tv_usec =
  2137.         ss->start_time.tv_sec =
  2138.         ss->start_time.tv_usec = 0L;
  2139. #endif
  2140.  
  2141.     }
  2142.  
  2143.     put_scoreboard_info(child_num, ss);
  2144. }
  2145.  
  2146. static void increment_counts(int child_num, request_rec *r)
  2147. {
  2148.     long int bs = 0;
  2149.     short_score *ss;
  2150.  
  2151.     ap_sync_scoreboard_image();
  2152.     ss = &ap_scoreboard_image->servers[child_num];
  2153.  
  2154.     if (r->sent_bodyct)
  2155.     ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
  2156.  
  2157. #ifndef NO_TIMES
  2158.     times(&ss->times);
  2159. #endif
  2160.     ss->access_count++;
  2161.     ss->my_access_count++;
  2162.     ss->conn_count++;
  2163.     ss->bytes_served += (unsigned long) bs;
  2164.     ss->my_bytes_served += (unsigned long) bs;
  2165.     ss->conn_bytes += (unsigned long) bs;
  2166.  
  2167.     put_scoreboard_info(child_num, ss);
  2168. }
  2169.  
  2170. static int find_child_by_pid(int pid)
  2171. {
  2172.     int i;
  2173.  
  2174.     for (i = 0; i < max_daemons_limit; ++i)
  2175.     if (ap_scoreboard_image->parent[i].pid == pid)
  2176.         return i;
  2177.  
  2178.     return -1;
  2179. }
  2180.  
  2181. static void reclaim_child_processes(int terminate)
  2182. {
  2183. #ifndef MULTITHREAD
  2184.     int i, status;
  2185.     long int waittime = 1024 * 16;    /* in usecs */
  2186.     struct timeval tv;
  2187.     int waitret, tries;
  2188.     int not_dead_yet;
  2189. #ifndef NO_OTHER_CHILD
  2190.     other_child_rec *ocr, *nocr;
  2191. #endif
  2192.  
  2193.     ap_sync_scoreboard_image();
  2194.  
  2195.     for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
  2196.     /* don't want to hold up progress any more than 
  2197.      * necessary, but we need to allow children a few moments to exit.
  2198.      * Set delay with an exponential backoff.
  2199.      */
  2200.     tv.tv_sec = waittime / 1000000;
  2201.     tv.tv_usec = waittime % 1000000;
  2202.     waittime = waittime * 4;
  2203.     ap_select(0, NULL, NULL, NULL, &tv);
  2204.  
  2205.     /* now see who is done */
  2206.     not_dead_yet = 0;
  2207.     for (i = 0; i < max_daemons_limit; ++i) {
  2208.         int pid = ap_scoreboard_image->parent[i].pid;
  2209.  
  2210.         if (pid == my_pid || pid == 0)
  2211.         continue;
  2212.  
  2213.         waitret = waitpid(pid, &status, WNOHANG);
  2214.         if (waitret == pid || waitret == -1) {
  2215.         ap_scoreboard_image->parent[i].pid = 0;
  2216.         continue;
  2217.         }
  2218.         ++not_dead_yet;
  2219.         switch (tries) {
  2220.         case 1:     /*  16ms */
  2221.         case 2:     /*  82ms */
  2222.         break;
  2223.         case 3:     /* 344ms */
  2224.         /* perhaps it missed the SIGHUP, lets try again */
  2225.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
  2226.                 server_conf,
  2227.             "child process %d did not exit, sending another SIGHUP",
  2228.                 pid);
  2229.         kill(pid, SIGHUP);
  2230.         waittime = 1024 * 16;
  2231.         break;
  2232.         case 4:     /*  16ms */
  2233.         case 5:     /*  82ms */
  2234.         case 6:     /* 344ms */
  2235.         break;
  2236.         case 7:     /* 1.4sec */
  2237.         /* ok, now it's being annoying */
  2238.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
  2239.                 server_conf,
  2240.            "child process %d still did not exit, sending a SIGTERM",
  2241.                 pid);
  2242.         kill(pid, SIGTERM);
  2243.         break;
  2244.         case 8:     /*  6 sec */
  2245.         /* die child scum */
  2246.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
  2247.            "child process %d still did not exit, sending a SIGKILL",
  2248.                 pid);
  2249.         kill(pid, SIGKILL);
  2250.         break;
  2251.         case 9:     /* 14 sec */
  2252.         /* gave it our best shot, but alas...  If this really 
  2253.          * is a child we are trying to kill and it really hasn't
  2254.          * exited, we will likely fail to bind to the port
  2255.          * after the restart.
  2256.          */
  2257.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
  2258.                 "could not make child process %d exit, "
  2259.                 "attempting to continue anyway", pid);
  2260.         break;
  2261.         }
  2262.     }
  2263. #ifndef NO_OTHER_CHILD
  2264.     for (ocr = other_children; ocr; ocr = nocr) {
  2265.         nocr = ocr->next;
  2266.         if (ocr->pid == -1)
  2267.         continue;
  2268.  
  2269.         waitret = waitpid(ocr->pid, &status, WNOHANG);
  2270.         if (waitret == ocr->pid) {
  2271.         ocr->pid = -1;
  2272.         (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
  2273.         }
  2274.         else if (waitret == 0) {
  2275.         (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
  2276.         ++not_dead_yet;
  2277.         }
  2278.         else if (waitret == -1) {
  2279.         /* uh what the heck? they didn't call unregister? */
  2280.         ocr->pid = -1;
  2281.         (*ocr->maintenance) (OC_REASON_LOST, ocr->data, -1);
  2282.         }
  2283.     }
  2284. #endif
  2285.     if (!not_dead_yet) {
  2286.         /* nothing left to wait for */
  2287.         break;
  2288.     }
  2289.     }
  2290. #endif /* ndef MULTITHREAD */
  2291. }
  2292.  
  2293.  
  2294. #if defined(NEED_WAITPID)
  2295. /*
  2296.    Systems without a real waitpid sometimes lose a child's exit while waiting
  2297.    for another.  Search through the scoreboard for missing children.
  2298.  */
  2299. int reap_children(ap_wait_t *status)
  2300. {
  2301.     int n, pid;
  2302.  
  2303.     for (n = 0; n < max_daemons_limit; ++n) {
  2304.         ap_sync_scoreboard_image();
  2305.     if (ap_scoreboard_image->servers[n].status != SERVER_DEAD &&
  2306.         kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
  2307.         ap_update_child_status(n, SERVER_DEAD, NULL);
  2308.         /* just mark it as having a successful exit status */
  2309.         bzero((char *) status, sizeof(ap_wait_t));
  2310.         return(pid);
  2311.     }
  2312.     }
  2313.     return 0;
  2314. }
  2315. #endif
  2316.  
  2317. /* Finally, this routine is used by the caretaker process to wait for
  2318.  * a while...
  2319.  */
  2320.  
  2321. /* number of calls to wait_or_timeout between writable probes */
  2322. #ifndef INTERVAL_OF_WRITABLE_PROBES
  2323. #define INTERVAL_OF_WRITABLE_PROBES 10
  2324. #endif
  2325. static int wait_or_timeout_counter;
  2326.  
  2327. static int wait_or_timeout(ap_wait_t *status)
  2328. {
  2329. #ifdef WIN32
  2330. #define MAXWAITOBJ MAXIMUM_WAIT_OBJECTS
  2331.     HANDLE h[MAXWAITOBJ];
  2332.     int e[MAXWAITOBJ];
  2333.     int round, pi, hi, rv, err;
  2334.     for (round = 0; round <= (HARD_SERVER_LIMIT - 1) / MAXWAITOBJ + 1; round++) {
  2335.     hi = 0;
  2336.     for (pi = round * MAXWAITOBJ;
  2337.          (pi < (round + 1) * MAXWAITOBJ) && (pi < HARD_SERVER_LIMIT);
  2338.          pi++) {
  2339.         if (ap_scoreboard_image->servers[pi].status != SERVER_DEAD) {
  2340.         e[hi] = pi;
  2341.         h[hi++] = (HANDLE) ap_scoreboard_image->parent[pi].pid;
  2342.         }
  2343.  
  2344.     }
  2345.     if (hi > 0) {
  2346.         rv = WaitForMultipleObjects(hi, h, FALSE, 10000);
  2347.         if (rv == -1)
  2348.         err = GetLastError();
  2349.         if ((WAIT_OBJECT_0 <= (unsigned int) rv) && ((unsigned int) rv < (WAIT_OBJECT_0 + hi)))
  2350.         return (ap_scoreboard_image->parent[e[rv - WAIT_OBJECT_0]].pid);
  2351.         else if ((WAIT_ABANDONED_0 <= (unsigned int) rv) && ((unsigned int) rv < (WAIT_ABANDONED_0 + hi)))
  2352.         return (ap_scoreboard_image->parent[e[rv - WAIT_ABANDONED_0]].pid);
  2353.  
  2354.     }
  2355.     }
  2356.     return (-1);
  2357.  
  2358. #else /* WIN32 */
  2359.     struct timeval tv;
  2360.     int ret;
  2361.  
  2362.     ++wait_or_timeout_counter;
  2363.     if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
  2364.     wait_or_timeout_counter = 0;
  2365. #ifndef NO_OTHER_CHILD
  2366.     probe_writable_fds();
  2367. #endif
  2368.     }
  2369.     ret = waitpid(-1, status, WNOHANG);
  2370.     if (ret == -1 && errno == EINTR) {
  2371.     return -1;
  2372.     }
  2373.     if (ret > 0) {
  2374.     return ret;
  2375.     }
  2376. #ifdef NEED_WAITPID
  2377.     if ((ret = reap_children(status)) > 0) {
  2378.     return ret;
  2379.     }
  2380. #endif
  2381.     tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
  2382.     tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
  2383.     ap_select(0, NULL, NULL, NULL, &tv);
  2384.     return -1;
  2385. #endif /* WIN32 */
  2386. }
  2387.  
  2388.  
  2389. #if defined(NSIG)
  2390. #define NumSIG NSIG
  2391. #elif defined(_NSIG)
  2392. #define NumSIG _NSIG
  2393. #elif defined(__NSIG)
  2394. #define NumSIG __NSIG
  2395. #else
  2396. #define NumSIG 32   /* for 1998's unixes, this is still a good assumption */
  2397. #endif
  2398.  
  2399. #ifdef SYS_SIGLIST /* platform has sys_siglist[] */
  2400. #define INIT_SIGLIST()  /*nothing*/
  2401. #else /* platform has no sys_siglist[], define our own */
  2402. #define SYS_SIGLIST ap_sys_siglist
  2403. #define INIT_SIGLIST() siglist_init();
  2404.  
  2405. const char *ap_sys_siglist[NumSIG];
  2406.  
  2407. static void siglist_init(void)
  2408. {
  2409.     int sig;
  2410.  
  2411.     ap_sys_siglist[0] = "Signal 0";
  2412. #ifdef SIGHUP
  2413.     ap_sys_siglist[SIGHUP] = "Hangup";
  2414. #endif
  2415. #ifdef SIGINT
  2416.     ap_sys_siglist[SIGINT] = "Interrupt";
  2417. #endif
  2418. #ifdef SIGQUIT
  2419.     ap_sys_siglist[SIGQUIT] = "Quit";
  2420. #endif
  2421. #ifdef SIGILL
  2422.     ap_sys_siglist[SIGILL] = "Illegal instruction";
  2423. #endif
  2424. #ifdef SIGTRAP
  2425.     ap_sys_siglist[SIGTRAP] = "Trace/BPT trap";
  2426. #endif
  2427. #ifdef SIGIOT
  2428.     ap_sys_siglist[SIGIOT] = "IOT instruction";
  2429. #endif
  2430. #ifdef SIGABRT
  2431.     ap_sys_siglist[SIGABRT] = "Abort";
  2432. #endif
  2433. #ifdef SIGEMT
  2434.     ap_sys_siglist[SIGEMT] = "Emulator trap";
  2435. #endif
  2436. #ifdef SIGFPE
  2437.     ap_sys_siglist[SIGFPE] = "Arithmetic exception";
  2438. #endif
  2439. #ifdef SIGKILL
  2440.     ap_sys_siglist[SIGKILL] = "Killed";
  2441. #endif
  2442. #ifdef SIGBUS
  2443.     ap_sys_siglist[SIGBUS] = "Bus error";
  2444. #endif
  2445. #ifdef SIGSEGV
  2446.     ap_sys_siglist[SIGSEGV] = "Segmentation fault";
  2447. #endif
  2448. #ifdef SIGSYS
  2449.     ap_sys_siglist[SIGSYS] = "Bad system call";
  2450. #endif
  2451. #ifdef SIGPIPE
  2452.     ap_sys_siglist[SIGPIPE] = "Broken pipe";
  2453. #endif
  2454. #ifdef SIGALRM
  2455.     ap_sys_siglist[SIGALRM] = "Alarm clock";
  2456. #endif
  2457. #ifdef SIGTERM
  2458.     ap_sys_siglist[SIGTERM] = "Terminated";
  2459. #endif
  2460. #ifdef SIGUSR1
  2461.     ap_sys_siglist[SIGUSR1] = "User defined signal 1";
  2462. #endif
  2463. #ifdef SIGUSR2
  2464.     ap_sys_siglist[SIGUSR2] = "User defined signal 2";
  2465. #endif
  2466. #ifdef SIGCLD
  2467.     ap_sys_siglist[SIGCLD] = "Child status change";
  2468. #endif
  2469. #ifdef SIGCHLD
  2470.     ap_sys_siglist[SIGCHLD] = "Child status change";
  2471. #endif
  2472. #ifdef SIGPWR
  2473.     ap_sys_siglist[SIGPWR] = "Power-fail restart";
  2474. #endif
  2475. #ifdef SIGWINCH
  2476.     ap_sys_siglist[SIGWINCH] = "Window changed";
  2477. #endif
  2478. #ifdef SIGURG
  2479.     ap_sys_siglist[SIGURG] = "urgent socket condition";
  2480. #endif
  2481. #ifdef SIGPOLL
  2482.     ap_sys_siglist[SIGPOLL] = "Pollable event occurred";
  2483. #endif
  2484. #ifdef SIGIO
  2485.     ap_sys_siglist[SIGIO] = "socket I/O possible";
  2486. #endif
  2487. #ifdef SIGSTOP
  2488.     ap_sys_siglist[SIGSTOP] = "Stopped (signal)";
  2489. #endif
  2490. #ifdef SIGTSTP
  2491.     ap_sys_siglist[SIGTSTP] = "Stopped";
  2492. #endif
  2493. #ifdef SIGCONT
  2494.     ap_sys_siglist[SIGCONT] = "Continued";
  2495. #endif
  2496. #ifdef SIGTTIN
  2497.     ap_sys_siglist[SIGTTIN] = "Stopped (tty input)";
  2498. #endif
  2499. #ifdef SIGTTOU
  2500.     ap_sys_siglist[SIGTTOU] = "Stopped (tty output)";
  2501. #endif
  2502. #ifdef SIGVTALRM
  2503.     ap_sys_siglist[SIGVTALRM] = "virtual timer expired";
  2504. #endif
  2505. #ifdef SIGPROF
  2506.     ap_sys_siglist[SIGPROF] = "profiling timer expired";
  2507. #endif
  2508. #ifdef SIGXCPU
  2509.     ap_sys_siglist[SIGXCPU] = "exceeded cpu limit";
  2510. #endif
  2511. #ifdef SIGXFSZ
  2512.     ap_sys_siglist[SIGXFSZ] = "exceeded file size limit";
  2513. #endif
  2514.     for (sig=0; sig < sizeof(ap_sys_siglist)/sizeof(ap_sys_siglist[0]); ++sig)
  2515.         if (ap_sys_siglist[sig] == NULL)
  2516.             ap_sys_siglist[sig] = "";
  2517. }
  2518. #endif /* platform has sys_siglist[] */
  2519.  
  2520.  
  2521. /* handle all varieties of core dumping signals */
  2522. static void sig_coredump(int sig)
  2523. {
  2524.     chdir(ap_coredump_dir);
  2525.     signal(sig, SIG_DFL);
  2526. #ifndef WIN32
  2527.     kill(getpid(), sig);
  2528. #else
  2529.     raise(sig);
  2530. #endif
  2531.     /* At this point we've got sig blocked, because we're still inside
  2532.      * the signal handler.  When we leave the signal handler it will
  2533.      * be unblocked, and we'll take the signal... and coredump or whatever
  2534.      * is appropriate for this particular Unix.  In addition the parent
  2535.      * will see the real signal we received -- whereas if we called
  2536.      * abort() here, the parent would only see SIGABRT.
  2537.      */
  2538. }
  2539.  
  2540. /*****************************************************************
  2541.  * Connection structures and accounting...
  2542.  */
  2543.  
  2544. static void just_die(int sig)
  2545. {                /* SIGHUP to child process??? */
  2546.     /* if alarms are blocked we have to wait to die otherwise we might
  2547.      * end up with corruption in alloc.c's internal structures */
  2548.     if (alarms_blocked) {
  2549.     exit_after_unblock = 1;
  2550.     }
  2551.     else {
  2552.     clean_child_exit(0);
  2553.     }
  2554. }
  2555.  
  2556. static int volatile usr1_just_die = 1;
  2557. static int volatile deferred_die;
  2558.  
  2559. static void usr1_handler(int sig)
  2560. {
  2561.     if (usr1_just_die) {
  2562.     just_die(sig);
  2563.     }
  2564.     deferred_die = 1;
  2565. }
  2566.  
  2567. /* volatile just in case */
  2568. static int volatile shutdown_pending;
  2569. static int volatile restart_pending;
  2570. static int volatile is_graceful;
  2571. ap_generation_t volatile ap_my_generation;
  2572.  
  2573. #ifdef WIN32
  2574. /*
  2575.  * Signalling Apache on NT.
  2576.  *
  2577.  * Under Unix, Apache can be told to shutdown or restart by sending various
  2578.  * signals (HUP, USR, TERM). On NT we don't have easy access to signals, so
  2579.  * we use "events" instead. The parent apache process goes into a loop
  2580.  * where it waits forever for a set of events. Two of those events are
  2581.  * called
  2582.  *
  2583.  *    apPID_shutdown
  2584.  *    apPID_restart
  2585.  *
  2586.  * (where PID is the PID of the apache parent process). When one of these
  2587.  * is signalled, the Apache parent performs the appropriate action. The events
  2588.  * can become signalled through internal Apache methods (e.g. if the child
  2589.  * finds a fatal error and needs to kill its parent), via the service
  2590.  * control manager (the control thread will signal the shutdown event when
  2591.  * requested to stop the Apache service), from the -k Apache command line,
  2592.  * or from any external program which finds the Apache PID from the
  2593.  * httpd.pid file.
  2594.  *
  2595.  * The signal_parent() function, below, is used to signal one of these events.
  2596.  * It can be called by any child or parent process, since it does not
  2597.  * rely on global variables.
  2598.  *
  2599.  * On entry, type gives the event to signal. 0 means shutdown, 1 means 
  2600.  * graceful restart.
  2601.  */
  2602.  
  2603. static void signal_parent(int type)
  2604. {
  2605.     HANDLE e;
  2606.     char *signal_name;
  2607.     extern char signal_shutdown_name[];
  2608.     extern char signal_restart_name[];
  2609.  
  2610.     /* after updating the shutdown_pending or restart flags, we need
  2611.      * to wake up the parent process so it can see the changes. The
  2612.      * parent will normally be waiting for either a child process
  2613.      * to die, or for a signal on the "spache-signal" event. So set the
  2614.      * "apache-signal" event here.
  2615.      */
  2616.  
  2617.     if (one_process) {
  2618.     return;
  2619.     }
  2620.  
  2621.     switch(type) {
  2622.     case 0: signal_name = signal_shutdown_name; break;
  2623.     case 1: signal_name = signal_restart_name; break;
  2624.     default: return;
  2625.     }
  2626.  
  2627.     APD2("signal_parent signalling event \"%s\"", signal_name);
  2628.  
  2629.     e = OpenEvent(EVENT_ALL_ACCESS, FALSE, signal_name);
  2630.     if (!e) {
  2631.     /* Um, problem, can't signal the parent, which means we can't
  2632.      * signal ourselves to die. Ignore for now...
  2633.      */
  2634.     ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
  2635.         "OpenEvent on %s event", signal_name);
  2636.     return;
  2637.     }
  2638.     if (SetEvent(e) == 0) {
  2639.     /* Same problem as above */
  2640.     ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
  2641.         "SetEvent on %s event", signal_name);
  2642.     CloseHandle(e);
  2643.     return;
  2644.     }
  2645.     CloseHandle(e);
  2646. }
  2647. #endif
  2648.  
  2649. /*
  2650.  * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
  2651.  * functions to initiate shutdown or restart without relying on signals. 
  2652.  * Previously this was initiated in sig_term() and restart() signal handlers, 
  2653.  * but we want to be able to start a shutdown/restart from other sources --
  2654.  * e.g. on Win32, from the service manager. Now the service manager can
  2655.  * call ap_start_shutdown() or ap_start_restart() as appropiate.  Note that
  2656.  * these functions can also be called by the child processes, since global
  2657.  * variables are no longer used to pass on the required action to the parent.
  2658.  */
  2659.  
  2660. void ap_start_shutdown(void)
  2661. {
  2662. #ifndef WIN32
  2663.     if (shutdown_pending == 1) {
  2664.     /* Um, is this _probably_ not an error, if the user has
  2665.      * tried to do a shutdown twice quickly, so we won't
  2666.      * worry about reporting it.
  2667.      */
  2668.     return;
  2669.     }
  2670.     shutdown_pending = 1;
  2671. #else
  2672.     signal_parent(0);        /* get the parent process to wake up */
  2673. #endif
  2674. }
  2675.  
  2676. /* do a graceful restart if graceful == 1 */
  2677. void ap_start_restart(int graceful)
  2678. {
  2679. #ifndef WIN32
  2680.     if (restart_pending == 1) {
  2681.     /* Probably not an error - don't bother reporting it */
  2682.     return;
  2683.     }
  2684.     restart_pending = 1;
  2685.     is_graceful = graceful;
  2686. #else
  2687.     signal_parent(1);        /* get the parent process to wake up */
  2688. #endif /* WIN32 */
  2689. }
  2690.  
  2691. static void sig_term(int sig)
  2692. {
  2693.     ap_start_shutdown();
  2694. }
  2695.  
  2696. static void restart(int sig)
  2697. {
  2698. #ifndef WIN32
  2699.     ap_start_restart(sig == SIGUSR1);
  2700. #else
  2701.     ap_start_restart(1);
  2702. #endif
  2703. }
  2704.  
  2705. static void set_signals(void)
  2706. {
  2707. #ifndef NO_USE_SIGACTION
  2708.     struct sigaction sa;
  2709.  
  2710.     sigemptyset(&sa.sa_mask);
  2711.     sa.sa_flags = 0;
  2712.  
  2713.     if (!one_process) {
  2714.     sa.sa_handler = sig_coredump;
  2715. #if defined(SA_ONESHOT)
  2716.     sa.sa_flags = SA_ONESHOT;
  2717. #elif defined(SA_RESETHAND)
  2718.     sa.sa_flags = SA_RESETHAND;
  2719. #endif
  2720.     if (sigaction(SIGSEGV, &sa, NULL) < 0)
  2721.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGSEGV)");
  2722. #ifdef SIGBUS
  2723.     if (sigaction(SIGBUS, &sa, NULL) < 0)
  2724.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGBUS)");
  2725. #endif
  2726. #ifdef SIGABORT
  2727.     if (sigaction(SIGABORT, &sa, NULL) < 0)
  2728.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGABORT)");
  2729. #endif
  2730. #ifdef SIGABRT
  2731.     if (sigaction(SIGABRT, &sa, NULL) < 0)
  2732.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGABRT)");
  2733. #endif
  2734. #ifdef SIGILL
  2735.     if (sigaction(SIGILL, &sa, NULL) < 0)
  2736.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGILL)");
  2737. #endif
  2738.     sa.sa_flags = 0;
  2739.     }
  2740.     sa.sa_handler = sig_term;
  2741.     if (sigaction(SIGTERM, &sa, NULL) < 0)
  2742.     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGTERM)");
  2743. #ifdef SIGINT
  2744.     if (sigaction(SIGINT, &sa, NULL) < 0)
  2745.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGINT)");
  2746. #endif
  2747. #ifdef SIGXCPU
  2748.     sa.sa_handler = SIG_DFL;
  2749.     if (sigaction(SIGXCPU, &sa, NULL) < 0)
  2750.     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGXCPU)");
  2751. #endif
  2752. #ifdef SIGXFSZ
  2753.     sa.sa_handler = SIG_DFL;
  2754.     if (sigaction(SIGXFSZ, &sa, NULL) < 0)
  2755.     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGXFSZ)");
  2756. #endif
  2757.  
  2758.     /* we want to ignore HUPs and USR1 while we're busy processing one */
  2759.     sigaddset(&sa.sa_mask, SIGHUP);
  2760.     sigaddset(&sa.sa_mask, SIGUSR1);
  2761.     sa.sa_handler = restart;
  2762.     if (sigaction(SIGHUP, &sa, NULL) < 0)
  2763.     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGHUP)");
  2764.     if (sigaction(SIGUSR1, &sa, NULL) < 0)
  2765.     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGUSR1)");
  2766. #else
  2767.     if (!one_process) {
  2768.     signal(SIGSEGV, sig_coredump);
  2769. #ifdef SIGBUS
  2770.     signal(SIGBUS, sig_coredump);
  2771. #endif /* SIGBUS */
  2772. #ifdef SIGABORT
  2773.     signal(SIGABORT, sig_coredump);
  2774. #endif /* SIGABORT */
  2775. #ifdef SIGABRT
  2776.     signal(SIGABRT, sig_coredump);
  2777. #endif /* SIGABRT */
  2778. #ifdef SIGILL
  2779.     signal(SIGILL, sig_coredump);
  2780. #endif /* SIGILL */
  2781. #ifdef SIGXCPU
  2782.     signal(SIGXCPU, SIG_DFL);
  2783. #endif /* SIGXCPU */
  2784. #ifdef SIGXFSZ
  2785.     signal(SIGXFSZ, SIG_DFL);
  2786. #endif /* SIGXFSZ */
  2787.     }
  2788.  
  2789.     signal(SIGTERM, sig_term);
  2790. #ifdef SIGHUP
  2791.     signal(SIGHUP, restart);
  2792. #endif /* SIGHUP */
  2793. #ifdef SIGUSR1
  2794.     signal(SIGUSR1, restart);
  2795. #endif /* SIGUSR1 */
  2796. #endif
  2797. }
  2798.  
  2799.  
  2800. /*****************************************************************
  2801.  * Here follows a long bunch of generic server bookkeeping stuff...
  2802.  */
  2803.  
  2804. static void detach(void)
  2805. {
  2806. #if !defined(WIN32)
  2807.     int x;
  2808.  
  2809.     chdir("/");
  2810. #if !defined(MPE) && !defined(OS2) && !defined(TPF)
  2811. /* Don't detach for MPE because child processes can't survive the death of
  2812.    the parent. */
  2813.     if ((x = fork()) > 0)
  2814.     exit(0);
  2815.     else if (x == -1) {
  2816.     perror("fork");
  2817.     fprintf(stderr, "%s: unable to fork new process\n", ap_server_argv0);
  2818.     exit(1);
  2819.     }
  2820.     RAISE_SIGSTOP(DETACH);
  2821. #endif
  2822. #ifndef NO_SETSID
  2823.     if ((pgrp = setsid()) == -1) {
  2824.     perror("setsid");
  2825.     fprintf(stderr, "%s: setsid failed\n", ap_server_argv0);
  2826.     exit(1);
  2827.     }
  2828. #elif defined(NEXT) || defined(NEWSOS)
  2829.     if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) {
  2830.     perror("setpgrp");
  2831.     fprintf(stderr, "%s: setpgrp or getpgrp failed\n", ap_server_argv0);
  2832.     exit(1);
  2833.     }
  2834. #elif defined(OS2) || defined(TPF)
  2835.     /* OS/2 don't support process group IDs */
  2836.     pgrp = getpid();
  2837. #elif defined(MPE)
  2838.     /* MPE uses negative pid for process group */
  2839.     pgrp = -getpid();
  2840. #else
  2841.     if ((pgrp = setpgrp(getpid(), 0)) == -1) {
  2842.     perror("setpgrp");
  2843.     fprintf(stderr, "%s: setpgrp failed\n", ap_server_argv0);
  2844.     exit(1);
  2845.     }
  2846. #endif
  2847.  
  2848.     /* close out the standard file descriptors */
  2849.     if (freopen("/dev/null", "r", stdin) == NULL) {
  2850.     fprintf(stderr, "%s: unable to replace stdin with /dev/null: %s\n",
  2851.         ap_server_argv0, strerror(errno));
  2852.     /* continue anyhow -- note we can't close out descriptor 0 because we
  2853.      * have nothing to replace it with, and if we didn't have a descriptor
  2854.      * 0 the next file would be created with that value ... leading to
  2855.      * havoc.
  2856.      */
  2857.     }
  2858.     if (freopen("/dev/null", "w", stdout) == NULL) {
  2859.     fprintf(stderr, "%s: unable to replace stdout with /dev/null: %s\n",
  2860.         ap_server_argv0, strerror(errno));
  2861.     }
  2862.     /* stderr is a tricky one, we really want it to be the error_log,
  2863.      * but we haven't opened that yet.  So leave it alone for now and it'll
  2864.      * be reopened moments later.
  2865.      */
  2866. #endif /* ndef WIN32 */
  2867. }
  2868.  
  2869. /* Set group privileges.
  2870.  *
  2871.  * Note that we use the username as set in the config files, rather than
  2872.  * the lookup of to uid --- the same uid may have multiple passwd entries,
  2873.  * with different sets of groups for each.
  2874.  */
  2875.  
  2876. static void set_group_privs(void)
  2877. {
  2878. #ifndef WIN32
  2879.     if (!geteuid()) {
  2880.     char *name;
  2881.  
  2882.     /* Get username if passed as a uid */
  2883.  
  2884.     if (ap_user_name[0] == '#') {
  2885.         struct passwd *ent;
  2886.         uid_t uid = atoi(&ap_user_name[1]);
  2887.  
  2888.         if ((ent = getpwuid(uid)) == NULL) {
  2889.         ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  2890.              "getpwuid: couldn't determine user name from uid %u, "
  2891.              "you probably need to modify the User directive",
  2892.              (unsigned)uid);
  2893.         clean_child_exit(APEXIT_CHILDFATAL);
  2894.         }
  2895.  
  2896.         name = ent->pw_name;
  2897.     }
  2898.     else
  2899.         name = ap_user_name;
  2900.  
  2901. #ifndef OS2
  2902.     /* OS/2 dosen't support groups. */
  2903.  
  2904.     /* Reset `groups' attributes. */
  2905.  
  2906.     if (initgroups(name, ap_group_id) == -1) {
  2907.         ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  2908.             "initgroups: unable to set groups for User %s "
  2909.             "and Group %u", name, (unsigned)ap_group_id);
  2910.         clean_child_exit(APEXIT_CHILDFATAL);
  2911.     }
  2912. #ifdef MULTIPLE_GROUPS
  2913.     if (getgroups(NGROUPS_MAX, group_id_list) == -1) {
  2914.         ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  2915.             "getgroups: unable to get group list");
  2916.         clean_child_exit(APEXIT_CHILDFATAL);
  2917.     }
  2918. #endif
  2919.     if (setgid(ap_group_id) == -1) {
  2920.         ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  2921.             "setgid: unable to set group id to Group %u",
  2922.             (unsigned)ap_group_id);
  2923.         clean_child_exit(APEXIT_CHILDFATAL);
  2924.     }
  2925. #endif
  2926.     }
  2927. #endif /* ndef WIN32 */
  2928. }
  2929.  
  2930. /* check to see if we have the 'suexec' setuid wrapper installed */
  2931. static int init_suexec(void)
  2932. {
  2933. #ifndef WIN32
  2934.     struct stat wrapper;
  2935.  
  2936.     if ((stat(SUEXEC_BIN, &wrapper)) != 0)
  2937.     return (ap_suexec_enabled);
  2938.  
  2939.     if ((wrapper.st_mode & S_ISUID) && wrapper.st_uid == 0) {
  2940.     ap_suexec_enabled = 1;
  2941.     }
  2942. #endif /* ndef WIN32 */
  2943.     return (ap_suexec_enabled);
  2944. }
  2945.  
  2946. /*****************************************************************
  2947.  * Connection structures and accounting...
  2948.  */
  2949.  
  2950.  
  2951. static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
  2952.                  const struct sockaddr_in *remaddr,
  2953.                  const struct sockaddr_in *saddr,
  2954.                  int child_num)
  2955. {
  2956.     conn_rec *conn = (conn_rec *) ap_pcalloc(p, sizeof(conn_rec));
  2957.  
  2958.     /* Got a connection structure, so initialize what fields we can
  2959.      * (the rest are zeroed out by pcalloc).
  2960.      */
  2961.  
  2962.     conn->child_num = child_num;
  2963.  
  2964.     conn->pool = p;
  2965.     conn->local_addr = *saddr;
  2966.     conn->server = server; /* just a guess for now */
  2967.     ap_update_vhost_given_ip(conn);
  2968.     conn->base_server = conn->server;
  2969.     conn->client = inout;
  2970.  
  2971.     conn->remote_addr = *remaddr;
  2972.     conn->remote_ip = ap_pstrdup(conn->pool,
  2973.                   inet_ntoa(conn->remote_addr.sin_addr));
  2974.  
  2975.     return conn;
  2976. }
  2977.  
  2978. #if defined(TCP_NODELAY) && !defined(MPE)
  2979. static void sock_disable_nagle(int s)
  2980. {
  2981.     /* The Nagle algorithm says that we should delay sending partial
  2982.      * packets in hopes of getting more data.  We don't want to do
  2983.      * this; we are not telnet.  There are bad interactions between
  2984.      * persistent connections and Nagle's algorithm that have very severe
  2985.      * performance penalties.  (Failing to disable Nagle is not much of a
  2986.      * problem with simple HTTP.)
  2987.      *
  2988.      * In spite of these problems, failure here is not a shooting offense.
  2989.      */
  2990.     int just_say_no = 1;
  2991.  
  2992.     if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
  2993.            sizeof(int)) < 0) {
  2994.     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
  2995.             "setsockopt: (TCP_NODELAY)");
  2996.     }
  2997. }
  2998.  
  2999. #else
  3000. #define sock_disable_nagle(s)    /* NOOP */
  3001. #endif
  3002.  
  3003.  
  3004. static int make_sock(pool *p, const struct sockaddr_in *server)
  3005. {
  3006.     int s;
  3007.     int one = 1;
  3008.     char addr[512];
  3009.  
  3010.     if (server->sin_addr.s_addr != htonl(INADDR_ANY))
  3011.     ap_snprintf(addr, sizeof(addr), "address %s port %d",
  3012.         inet_ntoa(server->sin_addr), ntohs(server->sin_port));
  3013.     else
  3014.     ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
  3015.  
  3016.     /* note that because we're about to slack we don't use psocket */
  3017.     ap_block_alarms();
  3018.     if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
  3019.     ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
  3020.             "make_sock: failed to get a socket for %s", addr);
  3021.     ap_unblock_alarms();
  3022.     exit(1);
  3023.     }
  3024.  
  3025.     /* Solaris (probably versions 2.4, 2.5, and 2.5.1 with various levels
  3026.      * of tcp patches) has some really weird bugs where if you dup the
  3027.      * socket now it breaks things across SIGHUP restarts.  It'll either
  3028.      * be unable to bind, or it won't respond.
  3029.      */
  3030. #if defined (SOLARIS2) && SOLARIS2 < 260
  3031. #define WORKAROUND_SOLARIS_BUG
  3032. #endif
  3033.  
  3034.     /* PR#1282 Unixware 1.x appears to have the same problem as solaris */
  3035. #if defined (UW) && UW < 200
  3036. #define WORKAROUND_SOLARIS_BUG
  3037. #endif
  3038.  
  3039.     /* PR#1973 NCR SVR4 systems appear to have the same problem */
  3040. #if defined (MPRAS)
  3041. #define WORKAROUND_SOLARIS_BUG
  3042. #endif
  3043.  
  3044. #ifndef WORKAROUND_SOLARIS_BUG
  3045.     s = ap_slack(s, AP_SLACK_HIGH);
  3046.  
  3047.     ap_note_cleanups_for_socket(p, s);    /* arrange to close on exec or restart */
  3048. #endif
  3049.  
  3050. #ifndef MPE
  3051. /* MPE does not support SO_REUSEADDR and SO_KEEPALIVE */
  3052. #ifndef _OSD_POSIX
  3053.     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)) < 0) {
  3054.     ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
  3055.             "make_sock: for %s, setsockopt: (SO_REUSEADDR)", addr);
  3056.     close(s);
  3057.     ap_unblock_alarms();
  3058.     return -1;
  3059.     }
  3060. #endif /*_OSD_POSIX*/
  3061.     one = 1;
  3062. #ifndef BEOS
  3063. /* BeOS does not support SO_KEEPALIVE */
  3064.     if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(int)) < 0) {
  3065.     ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
  3066.             "make_sock: for %s, setsockopt: (SO_KEEPALIVE)", addr);
  3067.     close(s);
  3068.     ap_unblock_alarms();
  3069.     return -1;
  3070.     }
  3071. #endif
  3072. #endif
  3073.  
  3074.     sock_disable_nagle(s);
  3075.     sock_enable_linger(s);
  3076.  
  3077.     /*
  3078.      * To send data over high bandwidth-delay connections at full
  3079.      * speed we must force the TCP window to open wide enough to keep the
  3080.      * pipe full.  The default window size on many systems
  3081.      * is only 4kB.  Cross-country WAN connections of 100ms
  3082.      * at 1Mb/s are not impossible for well connected sites.
  3083.      * If we assume 100ms cross-country latency,
  3084.      * a 4kB buffer limits throughput to 40kB/s.
  3085.      *
  3086.      * To avoid this problem I've added the SendBufferSize directive
  3087.      * to allow the web master to configure send buffer size.
  3088.      *
  3089.      * The trade-off of larger buffers is that more kernel memory
  3090.      * is consumed.  YMMV, know your customers and your network!
  3091.      *
  3092.      * -John Heidemann <johnh@isi.edu> 25-Oct-96
  3093.      *
  3094.      * If no size is specified, use the kernel default.
  3095.      */
  3096. #ifndef BEOS            /* BeOS does not support SO_SNDBUF */
  3097.     if (server_conf->send_buffer_size) {
  3098.     if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
  3099.         (char *) &server_conf->send_buffer_size, sizeof(int)) < 0) {
  3100.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
  3101.             "make_sock: failed to set SendBufferSize for %s, "
  3102.             "using default", addr);
  3103.         /* not a fatal error */
  3104.     }
  3105.     }
  3106. #endif
  3107.  
  3108. #ifdef MPE
  3109. /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
  3110.     if (ntohs(server->sin_port) < 1024)
  3111.     GETPRIVMODE();
  3112. #endif
  3113.     if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
  3114.     ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
  3115.         "make_sock: could not bind to %s", addr);
  3116. #ifdef MPE
  3117.     if (ntohs(server->sin_port) < 1024)
  3118.         GETUSERMODE();
  3119. #endif
  3120.     close(s);
  3121.     ap_unblock_alarms();
  3122.     exit(1);
  3123.     }
  3124. #ifdef MPE
  3125.     if (ntohs(server->sin_port) < 1024)
  3126.     GETUSERMODE();
  3127. #endif
  3128.  
  3129.     if (listen(s, ap_listenbacklog) == -1) {
  3130.     ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  3131.         "make_sock: unable to listen for connections on %s", addr);
  3132.     close(s);
  3133.     ap_unblock_alarms();
  3134.     exit(1);
  3135.     }
  3136.  
  3137. #ifdef WORKAROUND_SOLARIS_BUG
  3138.     s = ap_slack(s, AP_SLACK_HIGH);
  3139.  
  3140.     ap_note_cleanups_for_socket(p, s);    /* arrange to close on exec or restart */
  3141. #endif
  3142.     ap_unblock_alarms();
  3143.  
  3144. #ifndef WIN32
  3145.     /* protect various fd_sets */
  3146.     if (s >= FD_SETSIZE) {
  3147.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
  3148.         "make_sock: problem listening on %s, filedescriptor (%u) "
  3149.         "larger than FD_SETSIZE (%u) "
  3150.         "found, you probably need to rebuild Apache with a "
  3151.         "larger FD_SETSIZE", addr, s, FD_SETSIZE);
  3152.     close(s);
  3153.     return -1;
  3154.     }
  3155. #endif
  3156.  
  3157.     return s;
  3158. }
  3159.  
  3160.  
  3161. /*
  3162.  * During a restart we keep track of the old listeners here, so that we
  3163.  * can re-use the sockets.  We have to do this because we won't be able
  3164.  * to re-open the sockets ("Address already in use").
  3165.  *
  3166.  * Unlike the listeners ring, old_listeners is a NULL terminated list.
  3167.  *
  3168.  * copy_listeners() makes the copy, find_listener() finds an old listener
  3169.  * and close_unused_listener() cleans up whatever wasn't used.
  3170.  */
  3171. static listen_rec *old_listeners;
  3172.  
  3173. /* unfortunately copy_listeners may be called before listeners is a ring */
  3174. static void copy_listeners(pool *p)
  3175. {
  3176.     listen_rec *lr;
  3177.  
  3178.     ap_assert(old_listeners == NULL);
  3179.     if (ap_listeners == NULL) {
  3180.     return;
  3181.     }
  3182.     lr = ap_listeners;
  3183.     do {
  3184.     listen_rec *nr = malloc(sizeof *nr);
  3185.     if (nr == NULL) {
  3186.         fprintf(stderr, "Ouch!  malloc failed in copy_listeners()\n");
  3187.         exit(1);
  3188.     }
  3189.     *nr = *lr;
  3190.     ap_kill_cleanups_for_socket(p, nr->fd);
  3191.     nr->next = old_listeners;
  3192.     ap_assert(!nr->used);
  3193.     old_listeners = nr;
  3194.     lr = lr->next;
  3195.     } while (lr && lr != ap_listeners);
  3196. }
  3197.  
  3198.  
  3199. static int find_listener(listen_rec *lr)
  3200. {
  3201.     listen_rec *or;
  3202.  
  3203.     for (or = old_listeners; or; or = or->next) {
  3204.     if (!memcmp(&or->local_addr, &lr->local_addr, sizeof(or->local_addr))) {
  3205.         or->used = 1;
  3206.         return or->fd;
  3207.     }
  3208.     }
  3209.     return -1;
  3210. }
  3211.  
  3212.  
  3213. static void close_unused_listeners(void)
  3214. {
  3215.     listen_rec *or, *next;
  3216.  
  3217.     for (or = old_listeners; or; or = next) {
  3218.     next = or->next;
  3219.     if (!or->used)
  3220.         closesocket(or->fd);
  3221.     free(or);
  3222.     }
  3223.     old_listeners = NULL;
  3224. }
  3225.  
  3226.  
  3227. /* open sockets, and turn the listeners list into a singly linked ring */
  3228. static void setup_listeners(pool *p)
  3229. {
  3230.     listen_rec *lr;
  3231.     int fd;
  3232.  
  3233.     listenmaxfd = -1;
  3234.     FD_ZERO(&listenfds);
  3235.     lr = ap_listeners;
  3236.     for (;;) {
  3237.     fd = find_listener(lr);
  3238.     if (fd < 0) {
  3239.         fd = make_sock(p, &lr->local_addr);
  3240.     }
  3241.     else {
  3242.         ap_note_cleanups_for_socket(p, fd);
  3243.     }
  3244.     if (fd >= 0) {
  3245.         FD_SET(fd, &listenfds);
  3246.         if (fd > listenmaxfd)
  3247.         listenmaxfd = fd;
  3248.     }
  3249.     lr->fd = fd;
  3250.     if (lr->next == NULL)
  3251.         break;
  3252.     lr = lr->next;
  3253.     }
  3254.     /* turn the list into a ring */
  3255.     lr->next = ap_listeners;
  3256.     head_listener = ap_listeners;
  3257.     close_unused_listeners();
  3258.  
  3259. #ifdef NO_SERIALIZED_ACCEPT
  3260.     /* warn them about the starvation problem if they're using multiple
  3261.      * sockets
  3262.      */
  3263.     if (ap_listeners->next != ap_listeners) {
  3264.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, NULL,
  3265.             "You cannot use multiple Listens safely on your system, "
  3266.             "proceeding anyway.  See src/PORTING, search for "
  3267.             "SERIALIZED_ACCEPT.");
  3268.     }
  3269. #endif
  3270. }
  3271.  
  3272.  
  3273. /*
  3274.  * Find a listener which is ready for accept().  This advances the
  3275.  * head_listener global.
  3276.  */
  3277. static ap_inline listen_rec *find_ready_listener(fd_set * main_fds)
  3278. {
  3279.     listen_rec *lr;
  3280.  
  3281.     lr = head_listener;
  3282.     do {
  3283.     if (FD_ISSET(lr->fd, main_fds)) {
  3284.         head_listener = lr->next;
  3285.         return (lr);
  3286.     }
  3287.     lr = lr->next;
  3288.     } while (lr != head_listener);
  3289.     return NULL;
  3290. }
  3291.  
  3292.  
  3293. #ifdef WIN32
  3294. static int s_iInitCount = 0;
  3295.  
  3296. static int AMCSocketInitialize(void)
  3297. {
  3298.     int iVersionRequested;
  3299.     WSADATA wsaData;
  3300.     int err;
  3301.  
  3302.     if (s_iInitCount > 0) {
  3303.     s_iInitCount++;
  3304.     return (0);
  3305.     }
  3306.     else if (s_iInitCount < 0)
  3307.     return (s_iInitCount);
  3308.  
  3309.     /* s_iInitCount == 0. Do the initailization */
  3310.     iVersionRequested = MAKEWORD(1, 1);
  3311.     err = WSAStartup((WORD) iVersionRequested, &wsaData);
  3312.     if (err) {
  3313.     s_iInitCount = -1;
  3314.     return (s_iInitCount);
  3315.     }
  3316.     if (LOBYTE(wsaData.wVersion) != 1 ||
  3317.     HIBYTE(wsaData.wVersion) != 1) {
  3318.     s_iInitCount = -2;
  3319.     WSACleanup();
  3320.     return (s_iInitCount);
  3321.     }
  3322.  
  3323.     s_iInitCount++;
  3324.     return (s_iInitCount);
  3325.  
  3326. }
  3327.  
  3328.  
  3329. static void AMCSocketCleanup(void)
  3330. {
  3331.     if (--s_iInitCount == 0)
  3332.     WSACleanup();
  3333.     return;
  3334. }
  3335. #endif
  3336.  
  3337. static void show_compile_settings(void)
  3338. {
  3339.     printf("Server version: %s\n", ap_get_server_version());
  3340.     printf("Server built:   %s\n", ap_get_server_built());
  3341.     printf("Server's Module Magic Number: %u:%u\n",
  3342.        MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
  3343.     printf("Server compiled with....\n");
  3344. #ifdef BIG_SECURITY_HOLE
  3345.     printf(" -D BIG_SECURITY_HOLE\n");
  3346. #endif
  3347. #ifdef SECURITY_HOLE_PASS_AUTHORIZATION
  3348.     printf(" -D SECURITY_HOLE_PASS_AUTHORIZATION\n");
  3349. #endif
  3350. #ifdef HAVE_MMAP
  3351.     printf(" -D HAVE_MMAP\n");
  3352. #endif
  3353. #ifdef HAVE_SHMGET
  3354.     printf(" -D HAVE_SHMGET\n");
  3355. #endif
  3356. #ifdef USE_MMAP_SCOREBOARD
  3357.     printf(" -D USE_MMAP_SCOREBOARD\n");
  3358. #endif
  3359. #ifdef USE_SHMGET_SCOREBOARD
  3360.     printf(" -D USE_SHMGET_SCOREBOARD\n");
  3361. #endif
  3362. #ifdef USE_OS2_SCOREBOARD
  3363.     printf(" -D USE_OS2_SCOREBOARD\n");
  3364. #endif
  3365. #ifdef USE_POSIX_SCOREBOARD
  3366.     printf(" -D USE_POSIX_SCOREBOARD\n");
  3367. #endif
  3368. #ifdef USE_MMAP_FILES
  3369.     printf(" -D USE_MMAP_FILES\n");
  3370. #ifdef MMAP_SEGMENT_SIZE
  3371.     printf(" -D MMAP_SEGMENT_SIZE=%ld\n",(long)MMAP_SEGMENT_SIZE);
  3372. #endif
  3373. #endif /*USE_MMAP_FILES*/
  3374. #ifdef NO_WRITEV
  3375.     printf(" -D NO_WRITEV\n");
  3376. #endif
  3377. #ifdef NO_LINGCLOSE
  3378.     printf(" -D NO_LINGCLOSE\n");
  3379. #endif
  3380. #ifdef USE_FCNTL_SERIALIZED_ACCEPT
  3381.     printf(" -D USE_FCNTL_SERIALIZED_ACCEPT\n");
  3382. #endif
  3383. #ifdef USE_FLOCK_SERIALIZED_ACCEPT
  3384.     printf(" -D USE_FLOCK_SERIALIZED_ACCEPT\n");
  3385. #endif
  3386. #ifdef USE_USLOCK_SERIALIZED_ACCEPT
  3387.     printf(" -D USE_USLOCK_SERIALIZED_ACCEPT\n");
  3388. #endif
  3389. #ifdef USE_SYSVSEM_SERIALIZED_ACCEPT
  3390.     printf(" -D USE_SYSVSEM_SERIALIZED_ACCEPT\n");
  3391. #endif
  3392. #ifdef USE_PTHREAD_SERIALIZED_ACCEPT
  3393.     printf(" -D USE_PTHREAD_SERIALIZED_ACCEPT\n");
  3394. #endif
  3395. #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
  3396.     printf(" -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT\n");
  3397. #endif
  3398. #ifdef NO_OTHER_CHILD
  3399.     printf(" -D NO_OTHER_CHILD\n");
  3400. #endif
  3401. #ifdef NO_RELIABLE_PIPED_LOGS
  3402.     printf(" -D NO_RELIABLE_PIPED_LOGS\n");
  3403. #endif
  3404. #ifdef BUFFERED_LOGS
  3405.     printf(" -D BUFFERED_LOGS\n");
  3406. #ifdef PIPE_BUF
  3407.     printf(" -D PIPE_BUF=%ld\n",(long)PIPE_BUF);
  3408. #endif
  3409. #endif
  3410. #ifdef MULTITHREAD
  3411.     printf(" -D MULTITHREAD\n");
  3412. #endif
  3413. #ifdef CHARSET_EBCDIC
  3414.     printf(" -D CHARSET_EBCDIC\n");
  3415. #endif
  3416. #ifdef NEED_HASHBANG_EMUL
  3417.     printf(" -D NEED_HASHBANG_EMUL\n");
  3418. #endif
  3419. #ifdef SHARED_CORE
  3420.     printf(" -D SHARED_CORE\n");
  3421. #endif
  3422.  
  3423. /* This list displays the compiled-in default paths: */
  3424. #ifdef HTTPD_ROOT
  3425.     printf(" -D HTTPD_ROOT=\"" HTTPD_ROOT "\"\n");
  3426. #endif
  3427. #ifdef SUEXEC_BIN
  3428.     printf(" -D SUEXEC_BIN=\"" SUEXEC_BIN "\"\n");
  3429. #endif
  3430. #ifdef SHARED_CORE_DIR
  3431.     printf(" -D SHARED_CORE_DIR=\"" SHARED_CORE_DIR "\"\n");
  3432. #endif
  3433. #ifdef DEFAULT_PIDLOG
  3434.     printf(" -D DEFAULT_PIDLOG=\"" DEFAULT_PIDLOG "\"\n");
  3435. #endif
  3436. #ifdef DEFAULT_SCOREBOARD
  3437.     printf(" -D DEFAULT_SCOREBOARD=\"" DEFAULT_SCOREBOARD "\"\n");
  3438. #endif
  3439. #ifdef DEFAULT_LOCKFILE
  3440.     printf(" -D DEFAULT_LOCKFILE=\"" DEFAULT_LOCKFILE "\"\n");
  3441. #endif
  3442. #ifdef DEFAULT_XFERLOG
  3443.     printf(" -D DEFAULT_XFERLOG=\"" DEFAULT_XFERLOG "\"\n");
  3444. #endif
  3445. #ifdef DEFAULT_ERRORLOG
  3446.     printf(" -D DEFAULT_ERRORLOG=\"" DEFAULT_ERRORLOG "\"\n");
  3447. #endif
  3448. #ifdef TYPES_CONFIG_FILE
  3449.     printf(" -D TYPES_CONFIG_FILE=\"" TYPES_CONFIG_FILE "\"\n");
  3450. #endif
  3451. #ifdef SERVER_CONFIG_FILE
  3452.     printf(" -D SERVER_CONFIG_FILE=\"" SERVER_CONFIG_FILE "\"\n");
  3453. #endif
  3454. #ifdef ACCESS_CONFIG_FILE
  3455.     printf(" -D ACCESS_CONFIG_FILE=\"" ACCESS_CONFIG_FILE "\"\n");
  3456. #endif
  3457. #ifdef RESOURCE_CONFIG_FILE
  3458.     printf(" -D RESOURCE_CONFIG_FILE=\"" RESOURCE_CONFIG_FILE "\"\n");
  3459. #endif
  3460. }
  3461.  
  3462.  
  3463. /* Some init code that's common between win32 and unix... well actually
  3464.  * some of it is #ifdef'd but was duplicated before anyhow.  This stuff
  3465.  * is still a mess.
  3466.  */
  3467. static void common_init(void)
  3468. {
  3469.     INIT_SIGLIST()
  3470. #ifdef AUX3
  3471.     (void) set42sig();
  3472. #endif
  3473.  
  3474. #ifdef WIN32
  3475.     /* Initialize the stupid sockets */
  3476.     AMCSocketInitialize();
  3477. #endif /* WIN32 */
  3478.  
  3479.     pconf = ap_init_alloc();
  3480.     ptrans = ap_make_sub_pool(pconf);
  3481.  
  3482.     ap_util_init();
  3483.     ap_util_uri_init();
  3484.  
  3485.     pcommands = ap_make_sub_pool(NULL);
  3486.     ap_server_pre_read_config  = ap_make_array(pcommands, 1, sizeof(char *));
  3487.     ap_server_post_read_config = ap_make_array(pcommands, 1, sizeof(char *));
  3488.     ap_server_config_defines   = ap_make_array(pcommands, 1, sizeof(char *));
  3489. }
  3490.  
  3491. #ifndef MULTITHREAD
  3492. /*****************************************************************
  3493.  * Child process main loop.
  3494.  * The following vars are static to avoid getting clobbered by longjmp();
  3495.  * they are really private to child_main.
  3496.  */
  3497.  
  3498. static int srv;
  3499. static int csd;
  3500. static int dupped_csd;
  3501. static int requests_this_child;
  3502. static fd_set main_fds;
  3503.  
  3504. API_EXPORT(void) ap_child_terminate(request_rec *r)
  3505. {
  3506.     r->connection->keepalive = 0;
  3507.     requests_this_child = ap_max_requests_per_child = 1;
  3508. }
  3509.  
  3510. static void child_main(int child_num_arg)
  3511. {
  3512.     NET_SIZE_T clen;
  3513.     struct sockaddr sa_server;
  3514.     struct sockaddr sa_client;
  3515.     listen_rec *lr;
  3516.  
  3517.     /* All of initialization is a critical section, we don't care if we're
  3518.      * told to HUP or USR1 before we're done initializing.  For example,
  3519.      * we could be half way through child_init_modules() when a restart
  3520.      * signal arrives, and we'd have no real way to recover gracefully
  3521.      * and exit properly.
  3522.      *
  3523.      * I suppose a module could take forever to initialize, but that would
  3524.      * be either a broken module, or a broken configuration (i.e. network
  3525.      * problems, file locking problems, whatever). -djg
  3526.      */
  3527.     ap_block_alarms();
  3528.  
  3529.     my_pid = getpid();
  3530.     csd = -1;
  3531.     dupped_csd = -1;
  3532.     my_child_num = child_num_arg;
  3533.     requests_this_child = 0;
  3534.  
  3535.     /* Get a sub pool for global allocations in this child, so that
  3536.      * we can have cleanups occur when the child exits.
  3537.      */
  3538.     pchild = ap_make_sub_pool(pconf);
  3539.  
  3540.     /* needs to be done before we switch UIDs so we have permissions */
  3541.     reopen_scoreboard(pchild);
  3542.     SAFE_ACCEPT(accept_mutex_child_init(pchild));
  3543.  
  3544.     set_group_privs();
  3545. #ifdef MPE
  3546.     /* Only try to switch if we're running as MANAGER.SYS */
  3547.     if (geteuid() == 1 && ap_user_id > 1) {
  3548.     GETPRIVMODE();
  3549.     if (setuid(ap_user_id) == -1) {
  3550.         GETUSERMODE();
  3551.         ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  3552.             "setuid: unable to change uid");
  3553.         exit(1);
  3554.     }
  3555.     GETUSERMODE();
  3556.     }
  3557. #else
  3558.     /* Only try to switch if we're running as root */
  3559.     if (!geteuid() && (
  3560. #ifdef _OSD_POSIX
  3561.     os_init_job_environment(server_conf, ap_user_name, one_process) != 0 || 
  3562. #endif
  3563.     setuid(ap_user_id) == -1)) {
  3564.     ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  3565.             "setuid: unable to change uid");
  3566.     clean_child_exit(APEXIT_CHILDFATAL);
  3567.     }
  3568. #endif
  3569.  
  3570.     ap_child_init_modules(pchild, server_conf);
  3571.  
  3572.     /* done with the initialization critical section */
  3573.     ap_unblock_alarms();
  3574.  
  3575.     (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
  3576.  
  3577.     /*
  3578.      * Setup the jump buffers so that we can return here after
  3579.      * a signal or a timeout (yeah, I know, same thing).
  3580.      */
  3581.     ap_setjmp(jmpbuffer);
  3582. #ifndef OS2
  3583. #ifdef SIGURG
  3584.     signal(SIGURG, timeout);
  3585. #endif
  3586. #endif
  3587.     signal(SIGPIPE, timeout);
  3588.     signal(SIGALRM, alrm_handler);
  3589.  
  3590. #ifdef OS2
  3591. /* Stop Ctrl-C/Ctrl-Break signals going to child processes */
  3592.     {
  3593.         unsigned long ulTimes;
  3594.         DosSetSignalExceptionFocus(0, &ulTimes);
  3595.     }
  3596. #endif
  3597.  
  3598.     while (1) {
  3599.     BUFF *conn_io;
  3600.     request_rec *r;
  3601.  
  3602.     /* Prepare to receive a SIGUSR1 due to graceful restart so that
  3603.      * we can exit cleanly.  Since we're between connections right
  3604.      * now it's the right time to exit, but we might be blocked in a
  3605.      * system call when the graceful restart request is made. */
  3606.     usr1_just_die = 1;
  3607.     signal(SIGUSR1, usr1_handler);
  3608.  
  3609.     /*
  3610.      * (Re)initialize this child to a pre-connection state.
  3611.      */
  3612.  
  3613.     ap_kill_timeout(0);    /* Cancel any outstanding alarms. */
  3614.     current_conn = NULL;
  3615.  
  3616.     ap_clear_pool(ptrans);
  3617.  
  3618.     ap_sync_scoreboard_image();
  3619.     if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
  3620.         clean_child_exit(0);
  3621.     }
  3622.  
  3623. #ifndef WIN32
  3624.     if ((ap_max_requests_per_child > 0
  3625.          && ++requests_this_child >= ap_max_requests_per_child)) {
  3626.         clean_child_exit(0);
  3627.     }
  3628. #else
  3629.     ++requests_this_child;
  3630. #endif
  3631.  
  3632.     (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
  3633.  
  3634.     /*
  3635.      * Wait for an acceptable connection to arrive.
  3636.      */
  3637.  
  3638.     /* Lock around "accept", if necessary */
  3639.     SAFE_ACCEPT(accept_mutex_on());
  3640.  
  3641.     for (;;) {
  3642.         if (ap_listeners->next != ap_listeners) {
  3643.         /* more than one socket */
  3644.         memcpy(&main_fds, &listenfds, sizeof(fd_set));
  3645.         srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, NULL);
  3646.  
  3647.         if (srv < 0 && errno != EINTR) {
  3648.             /* Single Unix documents select as returning errnos
  3649.              * EBADF, EINTR, and EINVAL... and in none of those
  3650.              * cases does it make sense to continue.  In fact
  3651.              * on Linux 2.0.x we seem to end up with EFAULT
  3652.              * occasionally, and we'd loop forever due to it.
  3653.              */
  3654.             ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
  3655.             clean_child_exit(1);
  3656.         }
  3657.  
  3658.         if (srv <= 0)
  3659.             continue;
  3660.  
  3661.         lr = find_ready_listener(&main_fds);
  3662.         if (lr == NULL)
  3663.             continue;
  3664.         sd = lr->fd;
  3665.         }
  3666.         else {
  3667.         /* only one socket, just pretend we did the other stuff */
  3668.         sd = ap_listeners->fd;
  3669.         }
  3670.  
  3671.         /* if we accept() something we don't want to die, so we have to
  3672.          * defer the exit
  3673.          */
  3674.         deferred_die = 0;
  3675.         usr1_just_die = 0;
  3676.         for (;;) {
  3677.         clen = sizeof(sa_client);
  3678.         csd = accept(sd, &sa_client, &clen);
  3679.         if (csd >= 0 || errno != EINTR)
  3680.             break;
  3681.         if (deferred_die) {
  3682.             /* we didn't get a socket, and we were told to die */
  3683.             clean_child_exit(0);
  3684.         }
  3685.         }
  3686.  
  3687.         if (csd >= 0)
  3688.         break;        /* We have a socket ready for reading */
  3689.         else {
  3690.  
  3691.         /* Our old behaviour here was to continue after accept()
  3692.          * errors.  But this leads us into lots of troubles
  3693.          * because most of the errors are quite fatal.  For
  3694.          * example, EMFILE can be caused by slow descriptor
  3695.          * leaks (say in a 3rd party module, or libc).  It's
  3696.          * foolish for us to continue after an EMFILE.  We also
  3697.          * seem to tickle kernel bugs on some platforms which
  3698.          * lead to never-ending loops here.  So it seems best
  3699.          * to just exit in most cases.
  3700.          */
  3701.                 switch (errno) {
  3702. #ifdef EPROTO
  3703.             /* EPROTO on certain older kernels really means
  3704.              * ECONNABORTED, so we need to ignore it for them.
  3705.              * See discussion in new-httpd archives nh.9701
  3706.              * search for EPROTO.
  3707.              *
  3708.              * Also see nh.9603, search for EPROTO:
  3709.              * There is potentially a bug in Solaris 2.x x<6,
  3710.              * and other boxes that implement tcp sockets in
  3711.              * userland (i.e. on top of STREAMS).  On these
  3712.              * systems, EPROTO can actually result in a fatal
  3713.              * loop.  See PR#981 for example.  It's hard to
  3714.              * handle both uses of EPROTO.
  3715.              */
  3716.                 case EPROTO:
  3717. #endif
  3718. #ifdef ECONNABORTED
  3719.                 case ECONNABORTED:
  3720. #endif
  3721.             /* Linux generates the rest of these, other tcp
  3722.              * stacks (i.e. bsd) tend to hide them behind
  3723.              * getsockopt() interfaces.  They occur when
  3724.              * the net goes sour or the client disconnects
  3725.              * after the three-way handshake has been done
  3726.              * in the kernel but before userland has picked
  3727.              * up the socket.
  3728.              */
  3729. #ifdef ECONNRESET
  3730.                 case ECONNRESET:
  3731. #endif
  3732. #ifdef ETIMEDOUT
  3733.                 case ETIMEDOUT:
  3734. #endif
  3735. #ifdef EHOSTUNREACH
  3736.         case EHOSTUNREACH:
  3737. #endif
  3738. #ifdef ENETUNREACH
  3739.         case ENETUNREACH:
  3740. #endif
  3741.                     break;
  3742.  
  3743.         default:
  3744.             ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  3745.                 "accept: (client socket)");
  3746.             clean_child_exit(1);
  3747.         }
  3748.         }
  3749.  
  3750.         /* go around again, safe to die */
  3751.         usr1_just_die = 1;
  3752.         if (deferred_die) {
  3753.         /* ok maybe not, see ya later */
  3754.         clean_child_exit(0);
  3755.         }
  3756.         /* or maybe we missed a signal, you never know on systems
  3757.          * without reliable signals
  3758.          */
  3759.         ap_sync_scoreboard_image();
  3760.         if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
  3761.         clean_child_exit(0);
  3762.         }
  3763.     }
  3764.  
  3765.     SAFE_ACCEPT(accept_mutex_off());    /* unlock after "accept" */
  3766.  
  3767.     /* We've got a socket, let's at least process one request off the
  3768.      * socket before we accept a graceful restart request.
  3769.      */
  3770.     signal(SIGUSR1, SIG_IGN);
  3771.  
  3772.     ap_note_cleanups_for_fd(ptrans, csd);
  3773.  
  3774.     /* protect various fd_sets */
  3775.     if (csd >= FD_SETSIZE) {
  3776.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
  3777.         "[csd] filedescriptor (%u) larger than FD_SETSIZE (%u) "
  3778.         "found, you probably need to rebuild Apache with a "
  3779.         "larger FD_SETSIZE", csd, FD_SETSIZE);
  3780.         continue;
  3781.     }
  3782.  
  3783.     /*
  3784.      * We now have a connection, so set it up with the appropriate
  3785.      * socket options, file descriptors, and read/write buffers.
  3786.      */
  3787.  
  3788.     clen = sizeof(sa_server);
  3789.     if (getsockname(csd, &sa_server, &clen) < 0) {
  3790.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "getsockname");
  3791.         continue;
  3792.     }
  3793.  
  3794.     sock_disable_nagle(csd);
  3795.  
  3796.     (void) ap_update_child_status(my_child_num, SERVER_BUSY_READ,
  3797.                    (request_rec *) NULL);
  3798.  
  3799.     conn_io = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
  3800.  
  3801. #ifdef B_SFIO
  3802.     (void) sfdisc(conn_io->sf_in, SF_POPDISC);
  3803.     sfdisc(conn_io->sf_in, bsfio_new(conn_io->pool, conn_io));
  3804.     sfsetbuf(conn_io->sf_in, NULL, 0);
  3805.  
  3806.     (void) sfdisc(conn_io->sf_out, SF_POPDISC);
  3807.     sfdisc(conn_io->sf_out, bsfio_new(conn_io->pool, conn_io));
  3808.     sfsetbuf(conn_io->sf_out, NULL, 0);
  3809. #endif
  3810.  
  3811.     dupped_csd = csd;
  3812. #if defined(NEED_DUPPED_CSD)
  3813.     if ((dupped_csd = dup(csd)) < 0) {
  3814.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  3815.             "dup: couldn't duplicate csd");
  3816.         dupped_csd = csd;    /* Oh well... */
  3817.     }
  3818.     ap_note_cleanups_for_fd(ptrans, dupped_csd);
  3819.  
  3820.     /* protect various fd_sets */
  3821.     if (dupped_csd >= FD_SETSIZE) {
  3822.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
  3823.         "[dupped_csd] filedescriptor (%u) larger than FD_SETSIZE (%u) "
  3824.         "found, you probably need to rebuild Apache with a "
  3825.         "larger FD_SETSIZE", dupped_csd, FD_SETSIZE);
  3826.         continue;
  3827.     }
  3828. #endif
  3829.     ap_bpushfd(conn_io, csd, dupped_csd);
  3830.  
  3831.     current_conn = new_connection(ptrans, server_conf, conn_io,
  3832.                           (struct sockaddr_in *) &sa_client,
  3833.                           (struct sockaddr_in *) &sa_server,
  3834.                           my_child_num);
  3835.  
  3836.     /*
  3837.      * Read and process each request found on our connection
  3838.      * until no requests are left or we decide to close.
  3839.      */
  3840.  
  3841.     while ((r = ap_read_request(current_conn)) != NULL) {
  3842.  
  3843.         /* read_request_line has already done a
  3844.          * signal (SIGUSR1, SIG_IGN);
  3845.          */
  3846.  
  3847.         (void) ap_update_child_status(my_child_num, SERVER_BUSY_WRITE, r);
  3848.  
  3849.         /* process the request if it was read without error */
  3850.  
  3851.         if (r->status == HTTP_OK)
  3852.         ap_process_request(r);
  3853.  
  3854.         if(ap_extended_status)
  3855.         increment_counts(my_child_num, r);
  3856.  
  3857.         if (!current_conn->keepalive || current_conn->aborted)
  3858.         break;
  3859.  
  3860.         ap_destroy_pool(r->pool);
  3861.         (void) ap_update_child_status(my_child_num, SERVER_BUSY_KEEPALIVE,
  3862.                        (request_rec *) NULL);
  3863.  
  3864.         ap_sync_scoreboard_image();
  3865.         if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
  3866.         ap_bclose(conn_io);
  3867.         clean_child_exit(0);
  3868.         }
  3869.  
  3870.         /* In case we get a graceful restart while we're blocked
  3871.          * waiting for the request.
  3872.          *
  3873.          * XXX: This isn't perfect, we might actually read the
  3874.          * request and then just die without saying anything to
  3875.          * the client.  This can be fixed by using deferred_die
  3876.          * but you have to teach buff.c about it so that it can handle
  3877.          * the EINTR properly.
  3878.          *
  3879.          * In practice though browsers (have to) expect keepalive
  3880.          * connections to close before receiving a response because
  3881.          * of network latencies and server timeouts.
  3882.          */
  3883.         usr1_just_die = 1;
  3884.         signal(SIGUSR1, usr1_handler);
  3885.     }
  3886.  
  3887.     /*
  3888.      * Close the connection, being careful to send out whatever is still
  3889.      * in our buffers.  If possible, try to avoid a hard close until the
  3890.      * client has ACKed our FIN and/or has stopped sending us data.
  3891.      */
  3892.  
  3893. #ifdef NO_LINGCLOSE
  3894.     ap_bclose(conn_io);    /* just close it */
  3895. #else
  3896.     if (r && r->connection
  3897.         && !r->connection->aborted
  3898.         && r->connection->client
  3899.         && (r->connection->client->fd >= 0)) {
  3900.  
  3901.         lingering_close(r);
  3902.     }
  3903.     else {
  3904.         ap_bsetflag(conn_io, B_EOUT, 1);
  3905.         ap_bclose(conn_io);
  3906.     }
  3907. #endif
  3908.     }
  3909. }
  3910.  
  3911. static int make_child(server_rec *s, int slot, time_t now)
  3912. {
  3913.     int pid;
  3914.  
  3915.     if (slot + 1 > max_daemons_limit) {
  3916.     max_daemons_limit = slot + 1;
  3917.     }
  3918.  
  3919.     if (one_process) {
  3920.     signal(SIGHUP, just_die);
  3921.     signal(SIGINT, just_die);
  3922.     signal(SIGQUIT, SIG_DFL);
  3923.     signal(SIGTERM, just_die);
  3924.     child_main(slot);
  3925.     }
  3926.  
  3927.     /* avoid starvation */
  3928.     head_listener = head_listener->next;
  3929.  
  3930.     Explain1("Starting new child in slot %d", slot);
  3931.     (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
  3932.  
  3933.  
  3934. #ifndef _OSD_POSIX
  3935.     if ((pid = fork()) == -1) {
  3936. #else /*_OSD_POSIX*/
  3937.     /* BS2000 requires a "special" version of fork() before a setuid() call */
  3938.     if ((pid = os_fork()) == -1) {
  3939. #endif /*_OSD_POSIX*/
  3940.     ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process");
  3941.  
  3942.     /* fork didn't succeed. Fix the scoreboard or else
  3943.      * it will say SERVER_STARTING forever and ever
  3944.      */
  3945.     (void) ap_update_child_status(slot, SERVER_DEAD, (request_rec *) NULL);
  3946.  
  3947.     /* In case system resources are maxxed out, we don't want
  3948.        Apache running away with the CPU trying to fork over and
  3949.        over and over again. */
  3950.     sleep(10);
  3951.  
  3952.     return -1;
  3953.     }
  3954.  
  3955.     if (!pid) {
  3956. #ifdef AIX_BIND_PROCESSOR
  3957. /* by default AIX binds to a single processor
  3958.  * this bit unbinds children which will then bind to another cpu
  3959.  */
  3960. #include <sys/processor.h>
  3961.     int status = bindprocessor(BINDPROCESS, (int)getpid(), 
  3962.                    PROCESSOR_CLASS_ANY);
  3963.     if (status != OK) {
  3964.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
  3965.             "processor unbind failed %d", status);
  3966.     }
  3967. #endif
  3968.     RAISE_SIGSTOP(MAKE_CHILD);
  3969.     MONCONTROL(1);
  3970.     /* Disable the restart signal handlers and enable the just_die stuff.
  3971.      * Note that since restart() just notes that a restart has been
  3972.      * requested there's no race condition here.
  3973.      */
  3974.     signal(SIGHUP, just_die);
  3975.     signal(SIGUSR1, just_die);
  3976.     signal(SIGTERM, just_die);
  3977.     child_main(slot);
  3978.     }
  3979.  
  3980. #ifdef OPTIMIZE_TIMEOUTS
  3981.     ap_scoreboard_image->parent[slot].last_rtime = now;
  3982. #endif
  3983.     ap_scoreboard_image->parent[slot].pid = pid;
  3984. #ifdef SCOREBOARD_FILE
  3985.     lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[slot]), 0);
  3986.     force_write(scoreboard_fd, &ap_scoreboard_image->parent[slot],
  3987.         sizeof(parent_score));
  3988. #endif
  3989.  
  3990.     return 0;
  3991. }
  3992.  
  3993.  
  3994. /* start up a bunch of children */
  3995. static void startup_children(int number_to_start)
  3996. {
  3997.     int i;
  3998.     time_t now = time(0);
  3999.  
  4000.     for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
  4001.     if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
  4002.         continue;
  4003.     }
  4004.     if (make_child(server_conf, i, now) < 0) {
  4005.         break;
  4006.     }
  4007.     --number_to_start;
  4008.     }
  4009. }
  4010.  
  4011.  
  4012. /*
  4013.  * idle_spawn_rate is the number of children that will be spawned on the
  4014.  * next maintenance cycle if there aren't enough idle servers.  It is
  4015.  * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
  4016.  * without the need to spawn.
  4017.  */
  4018. static int idle_spawn_rate = 1;
  4019. #ifndef MAX_SPAWN_RATE
  4020. #define MAX_SPAWN_RATE    (32)
  4021. #endif
  4022. static int hold_off_on_exponential_spawning;
  4023.  
  4024. static void perform_idle_server_maintenance(void)
  4025. {
  4026.     int i;
  4027.     int to_kill;
  4028.     int idle_count;
  4029.     short_score *ss;
  4030.     time_t now = time(0);
  4031.     int free_length;
  4032.     int free_slots[MAX_SPAWN_RATE];
  4033.     int last_non_dead;
  4034.     int total_non_dead;
  4035.  
  4036.     /* initialize the free_list */
  4037.     free_length = 0;
  4038.  
  4039.     to_kill = -1;
  4040.     idle_count = 0;
  4041.     last_non_dead = -1;
  4042.     total_non_dead = 0;
  4043.  
  4044.     ap_sync_scoreboard_image();
  4045.     for (i = 0; i < ap_daemons_limit; ++i) {
  4046.     int status;
  4047.  
  4048.     if (i >= max_daemons_limit && free_length == idle_spawn_rate)
  4049.         break;
  4050.     ss = &ap_scoreboard_image->servers[i];
  4051.     status = ss->status;
  4052.     if (status == SERVER_DEAD) {
  4053.         /* try to keep children numbers as low as possible */
  4054.         if (free_length < idle_spawn_rate) {
  4055.         free_slots[free_length] = i;
  4056.         ++free_length;
  4057.         }
  4058.     }
  4059.     else {
  4060.         /* We consider a starting server as idle because we started it
  4061.          * at least a cycle ago, and if it still hasn't finished starting
  4062.          * then we're just going to swamp things worse by forking more.
  4063.          * So we hopefully won't need to fork more if we count it.
  4064.          * This depends on the ordering of SERVER_READY and SERVER_STARTING.
  4065.          */
  4066.         if (status <= SERVER_READY) {
  4067.         ++ idle_count;
  4068.         /* always kill the highest numbered child if we have to...
  4069.          * no really well thought out reason ... other than observing
  4070.          * the server behaviour under linux where lower numbered children
  4071.          * tend to service more hits (and hence are more likely to have
  4072.          * their data in cpu caches).
  4073.          */
  4074.         to_kill = i;
  4075.         }
  4076.  
  4077.         ++total_non_dead;
  4078.         last_non_dead = i;
  4079. #ifdef OPTIMIZE_TIMEOUTS
  4080.         if (ss->timeout_len) {
  4081.         /* if it's a live server, with a live timeout then
  4082.          * start checking its timeout */
  4083.         parent_score *ps = &ap_scoreboard_image->parent[i];
  4084.         if (ss->cur_vtime != ps->last_vtime) {
  4085.             /* it has made progress, so update its last_rtime,
  4086.              * last_vtime */
  4087.             ps->last_rtime = now;
  4088.             ps->last_vtime = ss->cur_vtime;
  4089.         }
  4090.         else if (ps->last_rtime + ss->timeout_len < now) {
  4091.             /* no progress, and the timeout length has been exceeded */
  4092.             ss->timeout_len = 0;
  4093.             kill(ps->pid, SIGALRM);
  4094.         }
  4095.         }
  4096. #endif
  4097.     }
  4098.     }
  4099.     max_daemons_limit = last_non_dead + 1;
  4100.     if (idle_count > ap_daemons_max_free) {
  4101.     /* kill off one child... we use SIGUSR1 because that'll cause it to
  4102.      * shut down gracefully, in case it happened to pick up a request
  4103.      * while we were counting
  4104.      */
  4105.     kill(ap_scoreboard_image->parent[to_kill].pid, SIGUSR1);
  4106.     idle_spawn_rate = 1;
  4107.     }
  4108.     else if (idle_count < ap_daemons_min_free) {
  4109.     /* terminate the free list */
  4110.     if (free_length == 0) {
  4111.         /* only report this condition once */
  4112.         static int reported = 0;
  4113.  
  4114.         if (!reported) {
  4115.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
  4116.                 "server reached MaxClients setting, consider"
  4117.                 " raising the MaxClients setting");
  4118.         reported = 1;
  4119.         }
  4120.         idle_spawn_rate = 1;
  4121.     }
  4122.     else {
  4123.         if (idle_spawn_rate >= 8) {
  4124.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
  4125.             "server seems busy, (you may need "
  4126.             "to increase StartServers, or Min/MaxSpareServers), "
  4127.             "spawning %d children, there are %d idle, and "
  4128.             "%d total children", idle_spawn_rate,
  4129.             idle_count, total_non_dead);
  4130.         }
  4131.         for (i = 0; i < free_length; ++i) {
  4132. #ifdef TPF
  4133.         if(make_child(server_conf, free_slots[i], now) == -1) {
  4134.             if(free_length == 1) {
  4135.                 shutdown_pending = 1;
  4136.                 ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
  4137.                 "No active child processes: shutting down");
  4138.             }
  4139.         }
  4140. #else
  4141.         make_child(server_conf, free_slots[i], now);
  4142. #endif /* TPF */
  4143.         }
  4144.         /* the next time around we want to spawn twice as many if this
  4145.          * wasn't good enough, but not if we've just done a graceful
  4146.          */
  4147.         if (hold_off_on_exponential_spawning) {
  4148.         --hold_off_on_exponential_spawning;
  4149.         }
  4150.         else if (idle_spawn_rate < MAX_SPAWN_RATE) {
  4151.         idle_spawn_rate *= 2;
  4152.         }
  4153.     }
  4154.     }
  4155.     else {
  4156.     idle_spawn_rate = 1;
  4157.     }
  4158. }
  4159.  
  4160.  
  4161. static void process_child_status(int pid, ap_wait_t status)
  4162. {
  4163.     /* Child died... if it died due to a fatal error,
  4164.     * we should simply bail out.
  4165.     */
  4166.     if ((WIFEXITED(status)) &&
  4167.     WEXITSTATUS(status) == APEXIT_CHILDFATAL) {
  4168.     ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server_conf,
  4169.             "Child %d returned a Fatal error... \n"
  4170.             "Apache is exiting!",
  4171.             pid);
  4172.     exit(APEXIT_CHILDFATAL);
  4173.     }
  4174.     if (WIFSIGNALED(status)) {
  4175.     switch (WTERMSIG(status)) {
  4176.     case SIGTERM:
  4177.     case SIGHUP:
  4178.     case SIGUSR1:
  4179.     case SIGKILL:
  4180.         break;
  4181.     default:
  4182. #ifdef SYS_SIGLIST
  4183. #ifdef WCOREDUMP
  4184.         if (WCOREDUMP(status)) {
  4185.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
  4186.                  server_conf,
  4187.                  "child pid %d exit signal %s (%d), "
  4188.                  "possible coredump in %s",
  4189.                  pid, (WTERMSIG(status) >= NumSIG) ? "" : 
  4190.                  SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status),
  4191.                  ap_coredump_dir);
  4192.         }
  4193.         else {
  4194. #endif
  4195.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
  4196.                  server_conf,
  4197.                  "child pid %d exit signal %s (%d)", pid,
  4198.                  SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status));
  4199. #ifdef WCOREDUMP
  4200.         }
  4201. #endif
  4202. #else
  4203.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
  4204.              server_conf,
  4205.              "child pid %d exit signal %d",
  4206.              pid, WTERMSIG(status));
  4207. #endif
  4208.     }
  4209.     }
  4210. }
  4211.  
  4212.  
  4213. /*****************************************************************
  4214.  * Executive routines.
  4215.  */
  4216.  
  4217. #ifndef STANDALONE_MAIN
  4218. #define STANDALONE_MAIN standalone_main
  4219.  
  4220. static void standalone_main(int argc, char **argv)
  4221. {
  4222.     int remaining_children_to_start;
  4223.  
  4224. #ifdef OS2
  4225.     printf("%s \n", ap_get_server_version());
  4226. #endif
  4227.  
  4228.     ap_standalone = 1;
  4229.  
  4230.     is_graceful = 0;
  4231.  
  4232.     if (!one_process) {
  4233.     detach();
  4234.     }
  4235.     else {
  4236.     MONCONTROL(1);
  4237.     }
  4238.  
  4239.     my_pid = getpid();
  4240.  
  4241.     do {
  4242.     copy_listeners(pconf);
  4243.     if (!is_graceful) {
  4244.         ap_restart_time = time(NULL);
  4245.     }
  4246. #ifdef SCOREBOARD_FILE
  4247.     else if (scoreboard_fd != -1) {
  4248.         ap_kill_cleanup(pconf, NULL, cleanup_scoreboard_file);
  4249.         ap_kill_cleanups_for_fd(pconf, scoreboard_fd);
  4250.     }
  4251. #endif
  4252.     ap_clear_pool(pconf);
  4253.     ptrans = ap_make_sub_pool(pconf);
  4254.  
  4255.     server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
  4256.     setup_listeners(pconf);
  4257.     ap_open_logs(server_conf, pconf);
  4258.     ap_log_pid(pconf, ap_pid_fname);
  4259.     ap_set_version();    /* create our server_version string */
  4260.     ap_init_modules(pconf, server_conf);
  4261.     version_locked++;    /* no more changes to server_version */
  4262.     SAFE_ACCEPT(accept_mutex_init(pconf));
  4263.     if (!is_graceful) {
  4264.         reinit_scoreboard(pconf);
  4265.     }
  4266. #ifdef SCOREBOARD_FILE
  4267.     else {
  4268.         ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
  4269.         ap_note_cleanups_for_fd(pconf, scoreboard_fd);
  4270.     }
  4271. #endif
  4272.  
  4273.     set_signals();
  4274.  
  4275.     if (ap_daemons_max_free < ap_daemons_min_free + 1)    /* Don't thrash... */
  4276.         ap_daemons_max_free = ap_daemons_min_free + 1;
  4277.  
  4278.     /* If we're doing a graceful_restart then we're going to see a lot
  4279.      * of children exiting immediately when we get into the main loop
  4280.      * below (because we just sent them SIGUSR1).  This happens pretty
  4281.      * rapidly... and for each one that exits we'll start a new one until
  4282.      * we reach at least daemons_min_free.  But we may be permitted to
  4283.      * start more than that, so we'll just keep track of how many we're
  4284.      * supposed to start up without the 1 second penalty between each fork.
  4285.      */
  4286.     remaining_children_to_start = ap_daemons_to_start;
  4287.     if (remaining_children_to_start > ap_daemons_limit) {
  4288.         remaining_children_to_start = ap_daemons_limit;
  4289.     }
  4290.     if (!is_graceful) {
  4291.         startup_children(remaining_children_to_start);
  4292.         remaining_children_to_start = 0;
  4293.     }
  4294.     else {
  4295.         /* give the system some time to recover before kicking into
  4296.          * exponential mode */
  4297.         hold_off_on_exponential_spawning = 10;
  4298.     }
  4299.  
  4300.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
  4301.             "%s configured -- resuming normal operations",
  4302.             ap_get_server_version());
  4303.     if (ap_suexec_enabled) {
  4304.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
  4305.                  "suEXEC mechanism enabled (wrapper: %s)", SUEXEC_BIN);
  4306.     }
  4307.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
  4308.             "Server built: %s", ap_get_server_built());
  4309.     restart_pending = shutdown_pending = 0;
  4310.  
  4311.     while (!restart_pending && !shutdown_pending) {
  4312.         int child_slot;
  4313.         ap_wait_t status;
  4314.         int pid = wait_or_timeout(&status);
  4315.  
  4316.         /* XXX: if it takes longer than 1 second for all our children
  4317.          * to start up and get into IDLE state then we may spawn an
  4318.          * extra child
  4319.          */
  4320.         if (pid >= 0) {
  4321.         process_child_status(pid, status);
  4322.         /* non-fatal death... note that it's gone in the scoreboard. */
  4323.         ap_sync_scoreboard_image();
  4324.         child_slot = find_child_by_pid(pid);
  4325.         Explain2("Reaping child %d slot %d", pid, child_slot);
  4326.         if (child_slot >= 0) {
  4327.             (void) ap_update_child_status(child_slot, SERVER_DEAD,
  4328.                            (request_rec *) NULL);
  4329.             if (remaining_children_to_start
  4330.             && child_slot < ap_daemons_limit) {
  4331.             /* we're still doing a 1-for-1 replacement of dead
  4332.              * children with new children
  4333.              */
  4334.             make_child(server_conf, child_slot, time(0));
  4335.             --remaining_children_to_start;
  4336.             }
  4337. #ifndef NO_OTHER_CHILD
  4338.         }
  4339.         else if (reap_other_child(pid, status) == 0) {
  4340.             /* handled */
  4341. #endif
  4342.         }
  4343.         else if (is_graceful) {
  4344.             /* Great, we've probably just lost a slot in the
  4345.              * scoreboard.  Somehow we don't know about this
  4346.              * child.
  4347.              */
  4348.             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
  4349.                 "long lost child came home! (pid %d)", pid);
  4350.         }
  4351.         /* Don't perform idle maintenance when a child dies,
  4352.          * only do it when there's a timeout.  Remember only a
  4353.          * finite number of children can die, and it's pretty
  4354.          * pathological for a lot to die suddenly.
  4355.          */
  4356.         continue;
  4357.         }
  4358.         else if (remaining_children_to_start) {
  4359.         /* we hit a 1 second timeout in which none of the previous
  4360.          * generation of children needed to be reaped... so assume
  4361.          * they're all done, and pick up the slack if any is left.
  4362.          */
  4363.         startup_children(remaining_children_to_start);
  4364.         remaining_children_to_start = 0;
  4365.         /* In any event we really shouldn't do the code below because
  4366.          * few of the servers we just started are in the IDLE state
  4367.          * yet, so we'd mistakenly create an extra server.
  4368.          */
  4369.         continue;
  4370.         }
  4371.  
  4372.         perform_idle_server_maintenance();
  4373.     }
  4374.  
  4375.     if (shutdown_pending) {
  4376.         /* Time to gracefully shut down:
  4377.          * Kill child processes, tell them to call child_exit, etc...
  4378.          */
  4379.         if (ap_killpg(pgrp, SIGTERM) < 0) {
  4380.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGTERM");
  4381.         }
  4382.         reclaim_child_processes(1);        /* Start with SIGTERM */
  4383.  
  4384.         /* cleanup pid file on normal shutdown */
  4385.         {
  4386.         const char *pidfile = NULL;
  4387.         pidfile = ap_server_root_relative (pconf, ap_pid_fname);
  4388.         if ( pidfile != NULL && unlink(pidfile) == 0)
  4389.             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
  4390.                  server_conf,
  4391.                  "removed PID file %s (pid=%ld)",
  4392.                  pidfile, (long)getpid());
  4393.         }
  4394.  
  4395.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
  4396.             "caught SIGTERM, shutting down");
  4397.         clean_parent_exit(0);
  4398.     }
  4399.  
  4400.     /* we've been told to restart */
  4401.     signal(SIGHUP, SIG_IGN);
  4402.     signal(SIGUSR1, SIG_IGN);
  4403.  
  4404.     if (one_process) {
  4405.         /* not worth thinking about */
  4406.         clean_parent_exit(0);
  4407.     }
  4408.  
  4409.     /* advance to the next generation */
  4410.     /* XXX: we really need to make sure this new generation number isn't in
  4411.      * use by any of the children.
  4412.      */
  4413.     ++ap_my_generation;
  4414.     ap_scoreboard_image->global.running_generation = ap_my_generation;
  4415.     update_scoreboard_global();
  4416.  
  4417.     if (is_graceful) {
  4418. #ifndef SCOREBOARD_FILE
  4419.         int i;
  4420. #endif
  4421.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
  4422.             "SIGUSR1 received.  Doing graceful restart");
  4423.  
  4424.         /* kill off the idle ones */
  4425.         if (ap_killpg(pgrp, SIGUSR1) < 0) {
  4426.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGUSR1");
  4427.         }
  4428. #ifndef SCOREBOARD_FILE
  4429.         /* This is mostly for debugging... so that we know what is still
  4430.          * gracefully dealing with existing request.  But we can't really
  4431.          * do it if we're in a SCOREBOARD_FILE because it'll cause
  4432.          * corruption too easily.
  4433.          */
  4434.         ap_sync_scoreboard_image();
  4435.         for (i = 0; i < ap_daemons_limit; ++i) {
  4436.         if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
  4437.             ap_scoreboard_image->servers[i].status = SERVER_GRACEFUL;
  4438.         }
  4439.         }
  4440. #endif
  4441.     }
  4442.     else {
  4443.         /* Kill 'em off */
  4444.         if (ap_killpg(pgrp, SIGHUP) < 0) {
  4445.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGHUP");
  4446.         }
  4447.         reclaim_child_processes(0);        /* Not when just starting up */
  4448.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
  4449.             "SIGHUP received.  Attempting to restart");
  4450.     }
  4451.     } while (restart_pending);
  4452.  
  4453.     /*add_common_vars(NULL);*/
  4454. }                /* standalone_main */
  4455. #else
  4456. /* prototype */
  4457. void STANDALONE_MAIN(int argc, char **argv);
  4458. #endif /* STANDALONE_MAIN */
  4459.  
  4460. extern char *optarg;
  4461. extern int optind;
  4462.  
  4463. int REALMAIN(int argc, char *argv[])
  4464. {
  4465.     int c;
  4466.     int configtestonly = 0;
  4467.     int sock_in;
  4468.     int sock_out;
  4469.     char *s;
  4470.     
  4471. #ifdef SecureWare
  4472.     if (set_auth_parameters(argc, argv) < 0)
  4473.     perror("set_auth_parameters");
  4474.     if (getluid() < 0)
  4475.     if (setluid(getuid()) < 0)
  4476.         perror("setluid");
  4477.     if (setreuid(0, 0) < 0)
  4478.     perror("setreuid");
  4479. #endif
  4480.  
  4481. #ifdef SOCKS
  4482.     SOCKSinit(argv[0]);
  4483. #endif
  4484.  
  4485.     MONCONTROL(0);
  4486.  
  4487.     common_init();
  4488.     
  4489.     if ((s = strrchr(argv[0], '/')) != NULL) {
  4490.     ap_server_argv0 = ++s;
  4491.     }
  4492.     else {
  4493.     ap_server_argv0 = argv[0];
  4494.     }
  4495.     
  4496.     ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
  4497.     ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname));
  4498.  
  4499.     ap_setup_prelinked_modules();
  4500.  
  4501. #ifndef TPF
  4502.     while ((c = getopt(argc, argv,
  4503.                     "D:C:c:Xd:f:vVlLR:Sth"
  4504. #ifdef DEBUG_SIGSTOP
  4505.                     "Z:"
  4506. #endif
  4507.             )) != -1) {
  4508.     char **new;
  4509.     switch (c) {
  4510.     case 'c':
  4511.         new = (char **)ap_push_array(ap_server_post_read_config);
  4512.         *new = ap_pstrdup(pcommands, optarg);
  4513.         break;
  4514.     case 'C':
  4515.         new = (char **)ap_push_array(ap_server_pre_read_config);
  4516.         *new = ap_pstrdup(pcommands, optarg);
  4517.         break;
  4518.     case 'D':
  4519.         new = (char **)ap_push_array(ap_server_config_defines);
  4520.         *new = ap_pstrdup(pcommands, optarg);
  4521.         break;
  4522.     case 'd':
  4523.         ap_cpystrn(ap_server_root, optarg, sizeof(ap_server_root));
  4524.         break;
  4525.     case 'f':
  4526.         ap_cpystrn(ap_server_confname, optarg, sizeof(ap_server_confname));
  4527.         break;
  4528.     case 'v':
  4529.         ap_set_version();
  4530.         printf("Server version: %s\n", ap_get_server_version());
  4531.         printf("Server built:   %s\n", ap_get_server_built());
  4532.         exit(0);
  4533.     case 'V':
  4534.         ap_set_version();
  4535.         show_compile_settings();
  4536.         exit(0);
  4537.     case 'l':
  4538.         ap_show_modules();
  4539.         exit(0);
  4540.     case 'L':
  4541.         ap_show_directives();
  4542.         exit(0);
  4543.     case 'X':
  4544.         ++one_process;    /* Weird debugging mode. */
  4545.         break;
  4546. #ifdef DEBUG_SIGSTOP
  4547.     case 'Z':
  4548.         raise_sigstop_flags = atoi(optarg);
  4549.         break;
  4550. #endif
  4551. #ifdef SHARED_CORE
  4552.     case 'R':
  4553.         /* just ignore this option here, because it has only
  4554.          * effect when SHARED_CORE is used and then it was
  4555.          * already handled in the Shared Core Bootstrap
  4556.          * program.
  4557.          */
  4558.         break;
  4559. #endif
  4560.     case 'S':
  4561.         ap_dump_settings = 1;
  4562.         break;
  4563.     case 't':
  4564.         configtestonly = 1;
  4565.         break;
  4566.     case 'h':
  4567.         usage(argv[0]);
  4568.     case '?':
  4569.         usage(argv[0]);
  4570.     }
  4571.     }
  4572. #endif /* TPF */
  4573.  
  4574.     ap_suexec_enabled = init_suexec();
  4575.     server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
  4576.  
  4577.     if (configtestonly) {
  4578.         fprintf(stderr, "Syntax OK\n");
  4579.         exit(0);
  4580.     }
  4581.     if (ap_dump_settings) {
  4582.         exit(0);
  4583.     }
  4584.  
  4585.     child_timeouts = !ap_standalone || one_process;
  4586.  
  4587.     if (ap_standalone) {
  4588.     ap_open_logs(server_conf, pconf);
  4589.     ap_set_version();
  4590.     ap_init_modules(pconf, server_conf);
  4591.     version_locked++;
  4592.     STANDALONE_MAIN(argc, argv);
  4593.     }
  4594.     else {
  4595.     conn_rec *conn;
  4596.     request_rec *r;
  4597.     struct sockaddr sa_server, sa_client;
  4598.     BUFF *cio;
  4599.     NET_SIZE_T l;
  4600.  
  4601.     ap_set_version();
  4602.     /* Yes this is called twice. */
  4603.     ap_init_modules(pconf, server_conf);
  4604.     version_locked++;
  4605.     ap_open_logs(server_conf, pconf);
  4606.     ap_init_modules(pconf, server_conf);
  4607.     set_group_privs();
  4608.  
  4609. #ifdef MPE
  4610.     /* Only try to switch if we're running as MANAGER.SYS */
  4611.     if (geteuid() == 1 && ap_user_id > 1) {
  4612.         GETPRIVMODE();
  4613.         if (setuid(ap_user_id) == -1) {
  4614.         GETUSERMODE();
  4615.         ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  4616.                 "setuid: unable to change uid");
  4617.         exit(1);
  4618.         }
  4619.         GETUSERMODE();
  4620.     }
  4621. #else
  4622.     /* Only try to switch if we're running as root */
  4623.     if (!geteuid() && setuid(ap_user_id) == -1) {
  4624.         ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
  4625.             "setuid: unable to change uid");
  4626.         exit(1);
  4627.     }
  4628. #endif
  4629.     if (ap_setjmp(jmpbuffer)) {
  4630.         exit(0);
  4631.     }
  4632.  
  4633. #ifdef TPF
  4634.     signal(SIGALRM, alrm_handler);
  4635.     ecbptr()->ebrout = PRIMECRAS;
  4636. #endif /* TPF */
  4637.  
  4638. #ifdef TPF
  4639. /* TPF only passes the incoming socket number from the internet daemon
  4640.    in ebw000 */
  4641.     sock_in = * (int*)(&(ecbptr()->ebw000));
  4642.     sock_out = * (int*)(&(ecbptr()->ebw000));
  4643. #elif defined(MPE)
  4644. /* HP MPE 5.5 inetd only passes the incoming socket as stdin (fd 0), whereas
  4645.    HPUX inetd passes the incoming socket as stdin (fd 0) and stdout (fd 1).
  4646.    Go figure.  SR 5003355016 has been submitted to request that the existing
  4647.    functionality be documented, and then to enhance the functionality to be
  4648.    like HPUX. */
  4649.     sock_in = fileno(stdin);
  4650.     sock_out = fileno(stdin);
  4651. #else
  4652.     sock_in = fileno(stdin);
  4653.     sock_out = fileno(stdout);
  4654. #endif
  4655.  
  4656.     l = sizeof(sa_client);
  4657.     if ((getpeername(sock_in, &sa_client, &l)) < 0) {
  4658. /* get peername will fail if the input isn't a socket */
  4659.         perror("getpeername");
  4660.         memset(&sa_client, '\0', sizeof(sa_client));
  4661.     }
  4662.  
  4663.     l = sizeof(sa_server);
  4664.     if (getsockname(sock_in, &sa_server, &l) < 0) {
  4665.         perror("getsockname");
  4666.         fprintf(stderr, "Error getting local address\n");
  4667.         exit(1);
  4668.     }
  4669.     server_conf->port = ntohs(((struct sockaddr_in *) &sa_server)->sin_port);
  4670.     cio = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
  4671.         cio->fd = sock_out;
  4672.         cio->fd_in = sock_in;
  4673.     conn = new_connection(ptrans, server_conf, cio,
  4674.                       (struct sockaddr_in *) &sa_client,
  4675.                       (struct sockaddr_in *) &sa_server, -1);
  4676.  
  4677.     while ((r = ap_read_request(conn)) != NULL) {
  4678.  
  4679.         if (r->status == HTTP_OK)
  4680.         ap_process_request(r);
  4681.  
  4682.         if (!conn->keepalive || conn->aborted)
  4683.         break;
  4684.  
  4685.         ap_destroy_pool(r->pool);
  4686.     }
  4687.  
  4688.     ap_bclose(cio);
  4689.     }
  4690.     exit(0);
  4691. }
  4692.  
  4693. #else /* ndef MULTITHREAD */
  4694.  
  4695.  
  4696. /**********************************************************************
  4697.  * Multithreaded implementation
  4698.  *
  4699.  * This code is fairly specific to Win32.
  4700.  *
  4701.  * The model used to handle requests is a set of threads. One "main"
  4702.  * thread listens for new requests. When something becomes
  4703.  * available, it does a select and places the newly available socket
  4704.  * onto a list of "jobs" (add_job()). Then any one of a fixed number
  4705.  * of "worker" threads takes the top job off the job list with
  4706.  * remove_job() and handles that connection to completion. After
  4707.  * the connection has finished the thread is free to take another
  4708.  * job from the job list.
  4709.  *
  4710.  * In the code, the "main" thread is running within the worker_main()
  4711.  * function. The first thing this function does is create the
  4712.  * worker threads, which operate in the child_sub_main() function. The
  4713.  * main thread then goes into a loop within worker_main() where they
  4714.  * do a select() on the listening sockets. The select times out once
  4715.  * per second so that the thread can check for an "exit" signal
  4716.  * from the parent process (see below). If this signal is set, the 
  4717.  * thread can exit, but only after it has accepted all incoming
  4718.  * connections already in the listen queue (since Win32 appears
  4719.  * to through away listened but unaccepted connections when a 
  4720.  * process dies).
  4721.  *
  4722.  * Because the main and worker threads exist within a single process
  4723.  * they are vulnerable to crashes or memory leaks (crashes can also
  4724.  * be caused within modules, of course). There also needs to be a 
  4725.  * mechanism to perform restarts and shutdowns. This is done by
  4726.  * creating the main & worker threads within a subprocess. A
  4727.  * main process (the "parent process") creates one (or more) 
  4728.  * processes to do the work, then the parent sits around waiting
  4729.  * for the working process to die, in which case it starts a new
  4730.  * one. The parent process also handles restarts (by creating
  4731.  * a new working process then signalling the previous working process 
  4732.  * exit ) and shutdowns (by signalling the working process to exit).
  4733.  * The parent process operates within the master_main() function. This
  4734.  * process also handles requests from the service manager (NT only).
  4735.  *
  4736.  * Signalling between the parent and working process uses a Win32
  4737.  * event. Each child has a unique name for the event, which is
  4738.  * passed to it with the -Z argument when the child is spawned. The
  4739.  * parent sets (signals) this event to tell the child to die.
  4740.  * At present all children do a graceful die - they finish all
  4741.  * current jobs _and_ empty the listen queue before they exit.
  4742.  * A non-graceful die would need a second event. The -Z argument in
  4743.  * the child is also used to create the shutdown and restart events,
  4744.  * since the prefix (apPID) contains the parent process PID.
  4745.  *
  4746.  * The code below starts with functions at the lowest level -
  4747.  * worker threads, and works up to the top level - the main()
  4748.  * function of the parent process.
  4749.  *
  4750.  * The scoreboard (in process memory) contains details of the worker
  4751.  * threads (within the active working process). There is no shared
  4752.  * "scoreboard" between processes, since only one is ever active
  4753.  * at once (or at most, two, when one has been told to shutdown but
  4754.  * is processes outstanding requests, and a new one has been started).
  4755.  * This is controlled by a "start_mutex" which ensures only one working
  4756.  * process is active at once.
  4757.  **********************************************************************/
  4758.  
  4759. /* The code protected by #ifdef UNGRACEFUL_RESTARTS/#endif sections
  4760.  * could implement a sort-of ungraceful restart for Win32. instead of
  4761.  * graceful restarts. 
  4762.  *
  4763.  * However it does not work too well because it does not intercept a
  4764.  * connection already in progress (in child_sub_main()). We'd have to
  4765.  * get that to poll on the exit event. 
  4766.  */
  4767.  
  4768. /*
  4769.  * Definition of jobs, shared by main and worker threads.
  4770.  */
  4771.  
  4772. typedef struct joblist_s {
  4773.     struct joblist_s *next;
  4774.     int sock;
  4775. } joblist;
  4776.  
  4777. /*
  4778.  * Globals common to main and worker threads. This structure is not
  4779.  * used by the parent process.
  4780.  */
  4781.  
  4782. typedef struct globals_s {
  4783. #ifdef UNGRACEFUL_RESTART
  4784.     HANDLE thread_exit_event;
  4785. #else
  4786.     int exit_now;
  4787. #endif
  4788.     semaphore *jobsemaphore;
  4789.     joblist *jobhead;
  4790.     joblist *jobtail;
  4791.     mutex *jobmutex;
  4792.     int jobcount;
  4793. } globals;
  4794.  
  4795. globals allowed_globals =
  4796. {0, NULL, NULL, NULL, NULL, 0};
  4797.  
  4798. /*
  4799.  * add_job()/remove_job() - add or remove an accepted socket from the
  4800.  * list of sockets connected to clients. allowed_globals.jobmutex protects
  4801.  * against multiple concurrent access to the linked list of jobs.
  4802.  */
  4803.  
  4804. void add_job(int sock)
  4805. {
  4806.     joblist *new_job;
  4807.  
  4808.     ap_assert(allowed_globals.jobmutex);
  4809.     /* TODO: If too many jobs in queue, sleep, check for problems */
  4810.     ap_acquire_mutex(allowed_globals.jobmutex);
  4811.     new_job = (joblist *) malloc(sizeof(joblist));
  4812.     new_job->next = NULL;
  4813.     new_job->sock = sock;
  4814.     if (allowed_globals.jobtail != NULL)
  4815.     allowed_globals.jobtail->next = new_job;
  4816.     allowed_globals.jobtail = new_job;
  4817.     if (!allowed_globals.jobhead)
  4818.     allowed_globals.jobhead = new_job;
  4819.     allowed_globals.jobcount++;
  4820.     release_semaphore(allowed_globals.jobsemaphore);
  4821.     ap_release_mutex(allowed_globals.jobmutex);
  4822. }
  4823.  
  4824. int remove_job(void)
  4825. {
  4826.     joblist *job;
  4827.     int sock;
  4828.  
  4829. #ifdef UNGRACEFUL_RESTART
  4830.     HANDLE hObjects[2];
  4831.     int rv;
  4832.  
  4833.     hObjects[0] = allowed_globals.jobsemaphore;
  4834.     hObjects[1] = allowed_globals.thread_exit_event;
  4835.  
  4836.     rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
  4837.     ap_assert(rv != WAIT_FAILED);
  4838.     if (rv == WAIT_OBJECT_0 + 1) {
  4839.     /* thread_exit_now */
  4840.     APD1("thread got exit now event");
  4841.     return -1;
  4842.     }
  4843.     /* must be semaphore */
  4844. #else
  4845.     acquire_semaphore(allowed_globals.jobsemaphore);
  4846. #endif
  4847.     ap_assert(allowed_globals.jobmutex);
  4848.  
  4849. #ifdef UNGRACEFUL_RESTART
  4850.     if (!allowed_globals.jobhead) {
  4851. #else
  4852.     ap_acquire_mutex(allowed_globals.jobmutex);
  4853.     if (allowed_globals.exit_now && !allowed_globals.jobhead) {
  4854. #endif
  4855.     ap_release_mutex(allowed_globals.jobmutex);
  4856.     return (-1);
  4857.     }
  4858.     job = allowed_globals.jobhead;
  4859.     ap_assert(job);
  4860.     allowed_globals.jobhead = job->next;
  4861.     if (allowed_globals.jobhead == NULL)
  4862.     allowed_globals.jobtail = NULL;
  4863.     ap_release_mutex(allowed_globals.jobmutex);
  4864.     sock = job->sock;
  4865.     free(job);
  4866.     return (sock);
  4867. }
  4868.  
  4869. /*
  4870.  * child_sub_main() - this is the main loop for the worker threads
  4871.  *
  4872.  * Each thread runs within this function. They wait within remove_job()
  4873.  * for a job to become available, then handle all the requests on that
  4874.  * connection until it is closed, then return to remove_job().
  4875.  *
  4876.  * The worker thread will exit when it removes a job which contains
  4877.  * socket number -1. This provides a graceful thread exit, since
  4878.  * it will never exit during a connection.
  4879.  *
  4880.  * This code in this function is basically equivalent to the child_main()
  4881.  * from the multi-process (Unix) environment, except that we
  4882.  *
  4883.  *  - do not call child_init_modules (child init API phase)
  4884.  *  - block in remove_job, and when unblocked we have an already
  4885.  *    accepted socket, instead of blocking on a mutex or select().
  4886.  */
  4887.  
  4888. static void child_sub_main(int child_num)
  4889. {
  4890.     NET_SIZE_T clen;
  4891.     struct sockaddr sa_server;
  4892.     struct sockaddr sa_client;
  4893.     pool *ptrans;
  4894.     int requests_this_child = 0;
  4895.     int csd = -1;
  4896.     int dupped_csd = -1;
  4897.     int srv = 0;
  4898.  
  4899.     ptrans = ap_make_sub_pool(pconf);
  4900.  
  4901.     (void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
  4902.  
  4903.     /*
  4904.      * Setup the jump buffers so that we can return here after
  4905.      * a signal or a timeout (yeah, I know, same thing).
  4906.      */
  4907. #if defined(USE_LONGJMP)
  4908.     setjmp(jmpbuffer);
  4909. #else
  4910.     sigsetjmp(jmpbuffer, 1);
  4911. #endif
  4912. #ifdef SIGURG
  4913.     signal(SIGURG, timeout);
  4914. #endif
  4915.  
  4916.     while (1) {
  4917.     BUFF *conn_io;
  4918.     request_rec *r;
  4919.  
  4920.     /*
  4921.      * (Re)initialize this child to a pre-connection state.
  4922.      */
  4923.  
  4924.     ap_set_callback_and_alarm(NULL, 0);    /* Cancel any outstanding alarms. */
  4925.     timeout_req = NULL;    /* No request in progress */
  4926.     current_conn = NULL;
  4927. #ifdef SIGPIPE
  4928.     signal(SIGPIPE, timeout);
  4929. #endif
  4930.  
  4931.     ap_clear_pool(ptrans);
  4932.  
  4933.     (void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
  4934.  
  4935.     /* Get job from the job list. This will block until a job is ready.
  4936.      * If -1 is returned then the main thread wants us to exit.
  4937.      */
  4938.     csd = remove_job();
  4939.     if (csd == -1)
  4940.         break;        /* time to exit */
  4941.     requests_this_child++;
  4942.  
  4943.     ap_note_cleanups_for_socket(ptrans, csd);
  4944.  
  4945.     /*
  4946.      * We now have a connection, so set it up with the appropriate
  4947.      * socket options, file descriptors, and read/write buffers.
  4948.      */
  4949.  
  4950.     clen = sizeof(sa_server);
  4951.     if (getsockname(csd, &sa_server, &clen) < 0) {
  4952.         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "getsockname");
  4953.         continue;
  4954.     }
  4955.     clen = sizeof(sa_client);
  4956.     if ((getpeername(csd, &sa_client, &clen)) < 0) {
  4957.         /* get peername will fail if the input isn't a socket */
  4958.         perror("getpeername");
  4959.         memset(&sa_client, '\0', sizeof(sa_client));
  4960.     }
  4961.  
  4962.     sock_disable_nagle(csd);
  4963.  
  4964.     (void) ap_update_child_status(child_num, SERVER_BUSY_READ,
  4965.                    (request_rec *) NULL);
  4966.  
  4967.     conn_io = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
  4968.     dupped_csd = csd;
  4969. #if defined(NEED_DUPPED_CSD)
  4970.     if ((dupped_csd = dup(csd)) < 0) {
  4971.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  4972.             "dup: couldn't duplicate csd");
  4973.         dupped_csd = csd;    /* Oh well... */
  4974.     }
  4975.     ap_note_cleanups_for_socket(ptrans, dupped_csd);
  4976. #endif
  4977.     ap_bpushfd(conn_io, csd, dupped_csd);
  4978.  
  4979.     current_conn = new_connection(ptrans, server_conf, conn_io,
  4980.                           (struct sockaddr_in *) &sa_client,
  4981.                           (struct sockaddr_in *) &sa_server,
  4982.                           child_num);
  4983.  
  4984.     /*
  4985.      * Read and process each request found on our connection
  4986.      * until no requests are left or we decide to close.
  4987.      */
  4988.  
  4989.     while ((r = ap_read_request(current_conn)) != NULL) {
  4990.         (void) ap_update_child_status(child_num, SERVER_BUSY_WRITE, r);
  4991.  
  4992.         if (r->status == HTTP_OK)
  4993.         ap_process_request(r);
  4994.  
  4995.         if (ap_extended_status)
  4996.         increment_counts(child_num, r);
  4997.  
  4998.         if (!current_conn->keepalive || current_conn->aborted)
  4999.         break;
  5000.  
  5001.         ap_destroy_pool(r->pool);
  5002.         (void) ap_update_child_status(child_num, SERVER_BUSY_KEEPALIVE,
  5003.                        (request_rec *) NULL);
  5004.  
  5005.         ap_sync_scoreboard_image();
  5006.     }
  5007.  
  5008.     /*
  5009.      * Close the connection, being careful to send out whatever is still
  5010.      * in our buffers.  If possible, try to avoid a hard close until the
  5011.      * client has ACKed our FIN and/or has stopped sending us data.
  5012.      */
  5013.     ap_kill_cleanups_for_socket(ptrans, csd);
  5014.  
  5015. #ifdef NO_LINGCLOSE
  5016.     ap_bclose(conn_io);    /* just close it */
  5017. #else
  5018.     if (r && r->connection
  5019.         && !r->connection->aborted
  5020.         && r->connection->client
  5021.         && (r->connection->client->fd >= 0)) {
  5022.  
  5023.         lingering_close(r);
  5024.     }
  5025.     else {
  5026.         ap_bsetflag(conn_io, B_EOUT, 1);
  5027.         ap_bclose(conn_io);
  5028.     }
  5029. #endif
  5030.     }
  5031.     ap_destroy_pool(ptrans);
  5032.     (void) ap_update_child_status(child_num, SERVER_DEAD, NULL);
  5033. }
  5034.  
  5035.  
  5036. void child_main(int child_num_arg)
  5037. {
  5038.     /*
  5039.      * Only reason for this function, is to pass in
  5040.      * arguments to child_sub_main() on its stack so
  5041.      * that longjump doesn't try to corrupt its local
  5042.      * variables and I don't need to make those
  5043.      * damn variables static/global
  5044.      */
  5045.     child_sub_main(child_num_arg);
  5046. }
  5047.  
  5048.  
  5049.  
  5050. void cleanup_thread(thread **handles, int *thread_cnt, int thread_to_clean)
  5051. {
  5052.     int i;
  5053.  
  5054.     free_thread(handles[thread_to_clean]);
  5055.     for (i = thread_to_clean; i < ((*thread_cnt) - 1); i++)
  5056.     handles[i] = handles[i + 1];
  5057.     (*thread_cnt)--;
  5058. }
  5059. #ifdef WIN32
  5060. /*
  5061.  * The Win32 call WaitForMultipleObjects will only allow you to wait for 
  5062.  * a maximum of MAXIMUM_WAIT_OBJECTS (current 64).  Since the threading 
  5063.  * model in the multithreaded version of apache wants to use this call, 
  5064.  * we are restricted to a maximum of 64 threads.  This is a simplistic 
  5065.  * routine that will increase this size.
  5066.  */
  5067. DWORD wait_for_many_objects(DWORD nCount, CONST HANDLE *lpHandles, 
  5068.                             DWORD dwSeconds)
  5069. {
  5070.     time_t tStopTime;
  5071.     DWORD dwRet = WAIT_TIMEOUT;
  5072.     DWORD dwIndex=0;
  5073.     BOOL bFirst = TRUE;
  5074.   
  5075.     tStopTime = time(NULL) + dwSeconds;
  5076.   
  5077.     do {
  5078.         if (!bFirst)
  5079.             Sleep(1000);
  5080.         else
  5081.             bFirst = FALSE;
  5082.           
  5083.         for (dwIndex = 0; dwIndex * MAXIMUM_WAIT_OBJECTS < nCount; dwIndex++) {
  5084.             dwRet = WaitForMultipleObjects(
  5085.                         min(MAXIMUM_WAIT_OBJECTS, 
  5086.                             nCount - (dwIndex * MAXIMUM_WAIT_OBJECTS)),
  5087.                         lpHandles + (dwIndex * MAXIMUM_WAIT_OBJECTS), 
  5088.                         0, 0);
  5089.                                            
  5090.             if (dwRet != WAIT_TIMEOUT) {                                          
  5091.               break;
  5092.             }
  5093.         }
  5094.     } while((time(NULL) < tStopTime) && (dwRet == WAIT_TIMEOUT));
  5095.     
  5096.     return dwRet;
  5097. }
  5098. #endif
  5099. /*****************************************************************
  5100.  * Executive routines.
  5101.  */
  5102.  
  5103. extern void main_control_server(void *); /* in hellop.c */
  5104.  
  5105. event *exit_event;
  5106. mutex *start_mutex;
  5107.  
  5108. #define MAX_SIGNAL_NAME 30  /* Long enough for apPID_shutdown, where PID is an int */
  5109. char signal_name_prefix[MAX_SIGNAL_NAME];
  5110. char signal_restart_name[MAX_SIGNAL_NAME]; 
  5111. char signal_shutdown_name[MAX_SIGNAL_NAME];
  5112.  
  5113. #define MAX_SELECT_ERRORS 100
  5114.  
  5115. /*
  5116.  * Initialise the signal names, in the global variables signal_name_prefix, 
  5117.  * signal_restart_name and signal_shutdown_name.
  5118.  */
  5119.  
  5120. void setup_signal_names(char *prefix)
  5121. {
  5122.     ap_snprintf(signal_name_prefix, sizeof(signal_name_prefix), prefix);    
  5123.     ap_snprintf(signal_shutdown_name, sizeof(signal_shutdown_name), 
  5124.     "%s_shutdown", signal_name_prefix);    
  5125.     ap_snprintf(signal_restart_name, sizeof(signal_restart_name), 
  5126.     "%s_restart", signal_name_prefix);    
  5127.  
  5128.     APD2("signal prefix %s", signal_name_prefix);
  5129. }
  5130.  
  5131. /*
  5132.  * worker_main() is main loop for the child process. The loop in
  5133.  * this function becomes the controlling thread for the actually working
  5134.  * threads (which run in a loop in child_sub_main()).
  5135.  */
  5136.  
  5137. void worker_main(void)
  5138. {
  5139.     int nthreads;
  5140.     fd_set main_fds;
  5141.     int srv;
  5142.     int clen;
  5143.     int csd;
  5144.     struct sockaddr_in sa_client;
  5145.     int total_jobs = 0;
  5146.     thread **child_handles;
  5147.     int rv;
  5148.     time_t end_time;
  5149.     int i;
  5150.     struct timeval tv;
  5151.     int wait_time = 1;
  5152.     int start_exit = 0;
  5153.     int start_mutex_released = 0;
  5154.     int max_jobs_per_exe;
  5155.     int max_jobs_after_exit_request;
  5156.     HANDLE hObjects[2];
  5157.     int count_select_errors = 0;
  5158.     pool *pchild;
  5159.  
  5160.     pchild = ap_make_sub_pool(pconf);
  5161.  
  5162.     ap_standalone = 1;
  5163.     sd = -1;
  5164.     nthreads = ap_threads_per_child;
  5165.     max_jobs_after_exit_request = ap_excess_requests_per_child;
  5166.     max_jobs_per_exe = ap_max_requests_per_child;
  5167.     if (nthreads <= 0)
  5168.     nthreads = 40;
  5169.     if (max_jobs_per_exe <= 0)
  5170.     max_jobs_per_exe = 0;
  5171.     if (max_jobs_after_exit_request <= 0)
  5172.     max_jobs_after_exit_request = max_jobs_per_exe / 10;
  5173.  
  5174.     if (!one_process)
  5175.     detach();
  5176.  
  5177.     my_pid = getpid();
  5178.  
  5179.     ++ap_my_generation;
  5180.  
  5181.     copy_listeners(pconf);
  5182.     ap_restart_time = time(NULL);
  5183.  
  5184.     reinit_scoreboard(pconf);
  5185.  
  5186.     /*
  5187.      * Wait until we have permission to start accepting connections.
  5188.      * start_mutex is used to ensure that only one child ever
  5189.      * goes into the listen/accept loop at once. Also wait on exit_event,
  5190.      * in case we (this child) is told to die before we get a chance to
  5191.      * serve any requests.
  5192.      */
  5193.     hObjects[0] = (HANDLE)start_mutex;
  5194.     hObjects[1] = (HANDLE)exit_event;
  5195.     rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
  5196.     if (rv == WAIT_FAILED) {
  5197.     ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_WIN32ERROR, server_conf,
  5198.         "Waiting for start_mutex or exit_event -- process will exit");
  5199.  
  5200.     ap_destroy_pool(pchild);
  5201.     cleanup_scoreboard();
  5202.     exit(0);
  5203.     }
  5204.     if (rv == WAIT_OBJECT_0 + 1) {
  5205.     /* exit event signalled - exit now */
  5206.     ap_destroy_pool(pchild);
  5207.     cleanup_scoreboard();
  5208.     exit(0);
  5209.     }
  5210.     /* start_mutex obtained, continue into the select() loop */
  5211.  
  5212.     setup_listeners(pconf);
  5213.     if (listenmaxfd == -1) {
  5214.     /* Help, no sockets were made, better log something and exit */
  5215.     ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, NULL,
  5216.             "No sockets were created for listening");
  5217.  
  5218.     signal_parent(0);    /* tell parent to die */
  5219.  
  5220.     ap_destroy_pool(pchild);
  5221.     cleanup_scoreboard();
  5222.     exit(0);
  5223.     }
  5224.     set_signals();
  5225.  
  5226.     /*
  5227.      * - Initialize allowed_globals
  5228.      * - Create the thread table
  5229.      * - Spawn off threads
  5230.      * - Create listen socket set (done above)
  5231.      * - loop {
  5232.      *       wait for request
  5233.      *       create new job
  5234.      *   } while (!time to exit)
  5235.      * - Close all listeners
  5236.      * - Wait for all threads to complete
  5237.      * - Exit
  5238.      */
  5239.  
  5240.     ap_child_init_modules(pconf, server_conf);
  5241.  
  5242.     allowed_globals.jobsemaphore = create_semaphore(0);
  5243.     allowed_globals.jobmutex = ap_create_mutex(NULL);
  5244.  
  5245.     /* spawn off the threads */
  5246.     child_handles = (thread *) alloca(nthreads * sizeof(int));
  5247.     for (i = 0; i < nthreads; i++) {
  5248.     child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
  5249.     }
  5250.     if (nthreads > max_daemons_limit) {
  5251.     max_daemons_limit = nthreads;
  5252.     }
  5253.  
  5254.     while (1) {
  5255. #if SEVERELY_VERBOSE
  5256.     APD4("child PID %d: thread_main total_jobs=%d start_exit=%d",
  5257.         my_pid, total_jobs, start_exit);
  5258. #endif
  5259.     if ((max_jobs_per_exe && (total_jobs > max_jobs_per_exe) && !start_exit)) {
  5260.         start_exit = 1;
  5261.         wait_time = 1;
  5262.         ap_release_mutex(start_mutex);
  5263.         start_mutex_released = 1;
  5264.         APD2("process PID %d: start mutex released\n", my_pid);
  5265.     }
  5266.     if (!start_exit) {
  5267.         rv = WaitForSingleObject(exit_event, 0);
  5268.         ap_assert((rv == WAIT_TIMEOUT) || (rv == WAIT_OBJECT_0));
  5269.         if (rv == WAIT_OBJECT_0) {
  5270.         APD1("child: exit event signalled, exiting");
  5271.         start_exit = 1;
  5272.         /* Lets not break yet - we may have threads to clean up */
  5273.         /* break;*/
  5274.         }
  5275.         rv = wait_for_many_objects(nthreads, child_handles, 0);
  5276.         ap_assert(rv != WAIT_FAILED);
  5277.         if (rv != WAIT_TIMEOUT) {
  5278.         rv = rv - WAIT_OBJECT_0;
  5279.         ap_assert((rv >= 0) && (rv < nthreads));
  5280.         cleanup_thread(child_handles, &nthreads, rv);
  5281.         break;
  5282.         }
  5283.     }
  5284.  
  5285. #if 0
  5286.     /* Um, this made us exit before all the connections in our
  5287.      * listen queue were dealt with. 
  5288.      */
  5289.     if (start_exit && max_jobs_after_exit_request && (count_down-- < 0))
  5290.         break;
  5291. #endif
  5292.     tv.tv_sec = wait_time;
  5293.     tv.tv_usec = 0;
  5294.  
  5295.     memcpy(&main_fds, &listenfds, sizeof(fd_set));
  5296.     srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
  5297. #ifdef WIN32
  5298.     if (srv == SOCKET_ERROR) {
  5299.         /* Map the Win32 error into a standard Unix error condition */
  5300.         errno = WSAGetLastError();
  5301.         srv = -1;
  5302.     }
  5303. #endif /* WIN32 */
  5304.  
  5305.     if (srv < 0) {
  5306.         /* Error occurred - if EINTR, loop around with problem */
  5307.         if (errno != EINTR) {
  5308.         /* A "real" error occurred, log it and increment the count of
  5309.          * select errors. This count is used to ensure we don't go into
  5310.          * a busy loop of continuour errors.
  5311.          */
  5312.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
  5313.         count_select_errors++;
  5314.         if (count_select_errors > MAX_SELECT_ERRORS) {
  5315.             ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server_conf,
  5316.             "Too many errors in select loop. Child process exiting.");
  5317.             break;
  5318.         }
  5319.         }
  5320.         continue;
  5321.     }
  5322.     count_select_errors = 0;    /* reset count of errors */
  5323.     if (srv == 0) {
  5324.         if (start_exit)
  5325.         break;
  5326.         else
  5327.         continue;
  5328.     }
  5329.  
  5330.     {
  5331.         listen_rec *lr;
  5332.  
  5333.         lr = find_ready_listener(&main_fds);
  5334.         if (lr != NULL) {
  5335.         sd = lr->fd;
  5336.         }
  5337.     }
  5338.     do {
  5339.         clen = sizeof(sa_client);
  5340.         csd = accept(sd, (struct sockaddr *) &sa_client, &clen);
  5341. #ifdef WIN32
  5342.         if (csd == INVALID_SOCKET) {
  5343.         csd = -1;
  5344.         errno = WSAGetLastError();
  5345.         }
  5346. #endif /* WIN32 */
  5347.     } while (csd < 0 && errno == EINTR);
  5348.  
  5349.     if (csd < 0) {
  5350. #if defined(EPROTO) && defined(ECONNABORTED)
  5351.         if ((errno != EPROTO) && (errno != ECONNABORTED))
  5352. #elif defined(EPROTO)
  5353.         if (errno != EPROTO)
  5354. #elif defined(ECONNABORTED)
  5355.         if (errno != ECONNABORTED)
  5356. #endif
  5357.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  5358.                 "accept: (client socket)");
  5359.     }
  5360.     else {
  5361.         add_job(csd);
  5362.         total_jobs++;
  5363.     }
  5364.     }
  5365.       
  5366.     APD2("process PID %d exiting", my_pid);
  5367.  
  5368.     /* Get ready to shutdown and exit */
  5369.     allowed_globals.exit_now = 1;
  5370.     if (!start_mutex_released) {
  5371.     ap_release_mutex(start_mutex);
  5372.     }
  5373.  
  5374. #ifdef UNGRACEFUL_RESTART
  5375.     SetEvent(allowed_globals.thread_exit_event);
  5376. #else
  5377.     for (i = 0; i < nthreads; i++) {
  5378.     add_job(-1);
  5379.     }
  5380. #endif
  5381.  
  5382.     APD2("process PID %d waiting for worker threads to exit", my_pid);
  5383.     /* Wait for all your children */
  5384.     end_time = time(NULL) + 180;
  5385.     while (nthreads) {
  5386.         rv = wait_for_many_objects(nthreads, child_handles, 
  5387.                                    end_time - time(NULL));
  5388.     if (rv != WAIT_TIMEOUT) {
  5389.         rv = rv - WAIT_OBJECT_0;
  5390.         ap_assert((rv >= 0) && (rv < nthreads));
  5391.         cleanup_thread(child_handles, &nthreads, rv);
  5392.         continue;
  5393.     }
  5394.     break;
  5395.     }
  5396.  
  5397.     APD2("process PID %d killing remaining worker threads", my_pid);
  5398.     for (i = 0; i < nthreads; i++) {
  5399.     kill_thread(child_handles[i]);
  5400.     free_thread(child_handles[i]);
  5401.     }
  5402. #ifdef UNGRACEFUL_RESTART
  5403.     ap_assert(CloseHandle(allowed_globals.thread_exit_event));
  5404. #endif
  5405.     destroy_semaphore(allowed_globals.jobsemaphore);
  5406.     ap_destroy_mutex(allowed_globals.jobmutex);
  5407.  
  5408.     ap_child_exit_modules(pconf, server_conf);
  5409.     ap_destroy_pool(pchild);
  5410.  
  5411.     cleanup_scoreboard();
  5412.  
  5413.     APD2("process PID %d exited", my_pid);
  5414.     clean_parent_exit(0);
  5415. }                /* standalone_main */
  5416.  
  5417. /*
  5418.  * Spawn a child Apache process. The child process has the command line arguments from
  5419.  * argc and argv[], plus a -Z argument giving the name of an event. The child should
  5420.  * open and poll or wait on this event. When it is signalled, the child should die.
  5421.  * prefix is a prefix string for the event name.
  5422.  * 
  5423.  * The child_num argument on entry contains a serial number for this child (used to create
  5424.  * a unique event name). On exit, this number will have been incremented by one, ready
  5425.  * for the next call. 
  5426.  *
  5427.  * On exit, the value pointed to be *ev will contain the event created
  5428.  * to signal the new child process.
  5429.  *
  5430.  * The return value is the handle to the child process if successful, else -1. If -1 is
  5431.  * returned the error will already have been logged by ap_log_error().
  5432.  */
  5433.  
  5434. int create_event_and_spawn(int argc, char **argv, event **ev, int *child_num, char *prefix)
  5435. {
  5436.     char buf[40], mod[200];
  5437.     int i, rv;
  5438.     char **pass_argv = (char **) alloca(sizeof(char *) * (argc + 3));
  5439.     
  5440.     /* We need an event to tell the child process to kill itself when
  5441.      * the parent is doing a shutdown/restart. This will be named
  5442.      * apPID_CN where PID is the parent Apache process PID and 
  5443.      * N is a unique child serial number. prefix contains
  5444.      * the "apPID" part. The child will get the name of this
  5445.      * event as its -Z command line argument.
  5446.      */
  5447.     ap_snprintf(buf, sizeof(buf), "%s_C%d", prefix, ++(*child_num));
  5448.     _flushall();
  5449.     *ev = CreateEvent(NULL, TRUE, FALSE, buf);
  5450.     if (!*ev) {
  5451.     ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
  5452.         "could not create event for child process");
  5453.     return -1;
  5454.     }
  5455.     APD2("create_event_and_spawn(): created process kill event %s", buf);
  5456.  
  5457.     pass_argv[0] = argv[0];
  5458.     pass_argv[1] = "-Z";
  5459.     pass_argv[2] = buf;
  5460.     for (i = 1; i < argc; i++) {
  5461.     pass_argv[i + 2] = argv[i];
  5462.     }
  5463.     pass_argv[argc + 2] = NULL;
  5464.  
  5465.     rv = GetModuleFileName(NULL, mod, sizeof(mod));
  5466.     if (rv == sizeof(mod)) {
  5467.     /* mod[] was not big enough for our pathname */
  5468.     ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
  5469.         "Internal error: path to Apache process too long");
  5470.     return -1;
  5471.     }
  5472.     if (rv == 0) {
  5473.     ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
  5474.         "GetModuleFileName() for current process");
  5475.     return -1;
  5476.     }
  5477.     rv = spawnv(_P_NOWAIT, mod, pass_argv);
  5478.     if (rv == -1) {
  5479.     ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
  5480.         "spawn of child process %s failed", mod);
  5481.     return -1;
  5482.     }
  5483.  
  5484.     return rv;
  5485. }
  5486.  
  5487. /**********************************************************************
  5488.  * master_main - this is the parent (main) process. We create a
  5489.  * child process to do the work, then sit around waiting for either
  5490.  * the child to exit, or a restart or exit signal. If the child dies,
  5491.  * we just respawn a new one. If we have a shutdown or graceful restart,
  5492.  * tell the child to die when it is ready. If it is a non-graceful
  5493.  * restart, force the child to die immediately.
  5494.  **********************************************************************/
  5495.  
  5496. #define MAX_PROCESSES 50 /* must be < MAX_WAIT_OBJECTS-1 */
  5497.  
  5498. void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *processes)
  5499. {
  5500.     int i;
  5501.     int handle = 0;
  5502.  
  5503.     CloseHandle(handles[position]);
  5504.     CloseHandle(events[position]);
  5505.  
  5506.     handle = (int)handles[position];
  5507.  
  5508.     for (i = position; i < (*processes)-1; i++) {
  5509.     handles[i] = handles[i + 1];
  5510.     events[i] = events[i + 1];
  5511.     }
  5512.     (*processes)--;
  5513.  
  5514.     APD4("cleanup_processes: removed child in slot %d handle %d, max=%d", position, handle, *processes);
  5515. }
  5516.  
  5517. int create_process(HANDLE *handles, HANDLE *events, int *processes, int *child_num, char *kill_event_name, int argc, char **argv)
  5518. {
  5519.     int i = *processes;
  5520.     HANDLE kill_event;
  5521.     int child_handle;
  5522.  
  5523.     child_handle = create_event_and_spawn(argc, argv, &kill_event, child_num, kill_event_name);
  5524.     if (child_handle <= 0) {
  5525.     return -1;
  5526.     }
  5527.     handles[i] = (HANDLE)child_handle;
  5528.     events[i] = kill_event;
  5529.     (*processes)++;
  5530.  
  5531.     APD4("create_processes: created child in slot %d handle %d, max=%d", 
  5532.     (*processes)-1, handles[(*processes)-1], *processes);
  5533.  
  5534.     return 0;
  5535. }
  5536.  
  5537. int master_main(int argc, char **argv)
  5538. {
  5539.     int nchild = ap_daemons_to_start;
  5540.     event **ev;
  5541.     int *child;
  5542.     int child_num = 0;
  5543.     int rv, cld;
  5544.     char signal_prefix_string[100];
  5545.     int i;
  5546.     time_t tmstart;
  5547.     HANDLE signal_shutdown_event;    /* used to signal shutdown to parent */
  5548.     HANDLE signal_restart_event;    /* used to signal a restart to parent */
  5549.     HANDLE process_handles[MAX_PROCESSES];
  5550.     HANDLE process_kill_events[MAX_PROCESSES];
  5551.     int current_live_processes = 0; /* number of child process we know about */
  5552.     int processes_to_create = 0;    /* number of child processes to create */
  5553.     pool *pparent = NULL;  /* pool for the parent process. Cleaned on each restart */
  5554.  
  5555.     nchild = 1;        /* only allowed one child process for current generation */
  5556.     processes_to_create = nchild;
  5557.  
  5558.     is_graceful = 0;
  5559.  
  5560.     ap_snprintf(signal_prefix_string, sizeof(signal_prefix_string),
  5561.             "ap%d", getpid());
  5562.     setup_signal_names(signal_prefix_string);
  5563.  
  5564.     signal_shutdown_event = CreateEvent(NULL, TRUE, FALSE, signal_shutdown_name);
  5565.     if (!signal_shutdown_event) {
  5566.     ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
  5567.             "Cannot create shutdown event %s", signal_shutdown_name);
  5568.     exit(1);
  5569.     }
  5570.     APD2("master_main: created event %s", signal_shutdown_name);
  5571.     signal_restart_event = CreateEvent(NULL, TRUE, FALSE, signal_restart_name);
  5572.     if (!signal_restart_event) {
  5573.     CloseHandle(signal_shutdown_event);
  5574.     ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
  5575.             "Cannot create restart event %s", signal_restart_name);
  5576.     exit(1);
  5577.     }
  5578.     APD2("master_main: created event %s", signal_restart_name);
  5579.  
  5580.     start_mutex = ap_create_mutex(signal_prefix_string);
  5581.     ev = (event **) alloca(sizeof(event *) * nchild);
  5582.     child = (int *) alloca(sizeof(int) * (nchild+1));
  5583.  
  5584.     while (processes_to_create--) {
  5585.     service_set_status(SERVICE_START_PENDING);
  5586.     if (create_process(process_handles, process_kill_events, 
  5587.         ¤t_live_processes, &child_num, signal_prefix_string, argc, argv) < 0) {
  5588.         goto die_now;
  5589.     }
  5590.     }
  5591.  
  5592.     service_set_status(SERVICE_RUNNING);
  5593.  
  5594.     restart_pending = shutdown_pending = 0;
  5595.  
  5596.     do { /* restart-pending */
  5597.     if (!is_graceful) {
  5598.         ap_restart_time = time(NULL);
  5599.     }
  5600.     ap_clear_pool(pconf);
  5601.     pparent = ap_make_sub_pool(pconf);
  5602.  
  5603.     server_conf = ap_read_config(pconf, pparent, ap_server_confname);
  5604.     ap_open_logs(server_conf, pconf);
  5605.     ap_set_version();
  5606.     ap_init_modules(pconf, server_conf);
  5607.     version_locked++;
  5608.  
  5609.     restart_pending = shutdown_pending = 0;
  5610.  
  5611.     /* Wait for either a child process to die, or for the stop_event
  5612.      * to be signalled by the service manager or rpc server */
  5613.     while (1) {
  5614.         /* Next line will block forever until either a child dies, or we
  5615.          * get signalled on the "apache-signal" event (e.g. if the user is
  5616.          * requesting a shutdown/restart)
  5617.          */
  5618.         if (current_live_processes == 0) {
  5619.         /* Shouldn't happen, but better safe than sorry */
  5620.         ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, server_conf,
  5621.              "master_main: no child processes alive! creating one");
  5622.         if (create_process(process_handles, process_kill_events, 
  5623.             ¤t_live_processes, &child_num, signal_prefix_string, 
  5624.             argc, argv) < 0) {
  5625.             goto die_now;
  5626.         }
  5627.         if (processes_to_create) {
  5628.             processes_to_create--;
  5629.         }
  5630.         }
  5631.         process_handles[current_live_processes] = signal_shutdown_event;
  5632.         process_handles[current_live_processes+1] = signal_restart_event;
  5633.         rv = WaitForMultipleObjects(current_live_processes+2, (HANDLE *)process_handles, 
  5634.             FALSE, INFINITE);
  5635.         if (rv == WAIT_FAILED) {
  5636.         /* Something serious is wrong */
  5637.         ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_WIN32ERROR, server_conf,
  5638.             "WaitForMultipeObjects on process handles and apache-signal -- doing shutdown");
  5639.         shutdown_pending = 1;
  5640.         break;
  5641.         }
  5642.         if (rv == WAIT_TIMEOUT) {
  5643.         /* Hey, this cannot happen */
  5644.         ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  5645.             "WaitForMultipeObjects with INFINITE wait exited with WAIT_TIMEOUT");
  5646.         shutdown_pending = 1;
  5647.         }
  5648.  
  5649.         cld = rv - WAIT_OBJECT_0;
  5650.         APD4("main process: wait finished, cld=%d handle %d (max=%d)", cld, process_handles[cld], current_live_processes);
  5651.         if (cld == current_live_processes) {
  5652.         /* shutdown event signalled, we should exit now */
  5653.         if (ResetEvent(signal_shutdown_event) == 0) {
  5654.             ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
  5655.             "ResetEvent(signal_shutdown_event)");
  5656.             /* Continue -- since we are doing a shutdown anyway */
  5657.         }
  5658.         shutdown_pending = 1;
  5659.         APD3("main process: stop_event signalled: shutdown_pending=%d, restart_pending=%d",
  5660.             shutdown_pending, restart_pending);
  5661.         break;
  5662.         }
  5663.         if (cld == current_live_processes+1) {
  5664.         /* restart event signalled, we should exit now */
  5665.         if (ResetEvent(signal_restart_event) == 0) {
  5666.             ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
  5667.             "ResetEvent(signal_restart_event)");
  5668.             /* Continue -- hopefully the restart will fix the problem */
  5669.         }
  5670.         restart_pending = 1;
  5671.         APD3("main process: stop_event signalled: shutdown_pending=%d, restart_pending=%d",
  5672.             shutdown_pending, restart_pending);
  5673.         break;
  5674.         }
  5675.         ap_assert(cld < current_live_processes);
  5676.         cleanup_process(process_handles, process_kill_events, cld, ¤t_live_processes);
  5677.         APD2("main_process: child in slot %d died", rv);
  5678.         if (processes_to_create) {
  5679.         create_process(process_handles, process_kill_events, ¤t_live_processes, 
  5680.             &child_num, signal_prefix_string, argc, argv);
  5681.         processes_to_create--;
  5682.         }
  5683.     }
  5684.     if (!shutdown_pending && !restart_pending) {
  5685.         ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO, server_conf,
  5686.         "master_main: no shutdown or restart variables set -- doing shutdown");
  5687.         shutdown_pending = 1;
  5688.     }
  5689.     if (shutdown_pending) {
  5690.         /* tell all child processes to die */
  5691.         for (i = 0; i < current_live_processes; i++) {
  5692.         APD3("main process: signalling child #%d handle %d to die", i, process_handles[i]);
  5693.         if (SetEvent(process_kill_events[i]) == 0)
  5694.             ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, server_conf,
  5695.             "SetEvent for child process in slot #%d", i);
  5696.         }
  5697.         break;
  5698.     }
  5699.     if (restart_pending) {
  5700.         int children_to_kill = current_live_processes;
  5701.  
  5702.         APD1("--- Doing graceful restart ---");
  5703.  
  5704.         processes_to_create = nchild;
  5705.         for (i = 0; i < nchild; ++i) {
  5706.         if (current_live_processes >= MAX_PROCESSES)
  5707.             break;
  5708.         create_process(process_handles, process_kill_events, ¤t_live_processes, 
  5709.             &child_num, signal_prefix_string, argc, argv);
  5710.         processes_to_create--;
  5711.         }
  5712.         for (i = 0; i < children_to_kill; i++) {
  5713.         APD3("main process: signalling child #%d handle %d to die", i, process_handles[i]);
  5714.         if (SetEvent(process_kill_events[i]) == 0)
  5715.             ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, server_conf,
  5716.              "SetEvent for child process in slot #%d", i);
  5717.         }
  5718.     }
  5719.     ++ap_my_generation;
  5720.     } while (restart_pending);
  5721.  
  5722.     /* If we dropped out of the loop we definitly want to die completely. We need to
  5723.      * make sure we wait for all the child process to exit first.
  5724.      */
  5725.  
  5726.     APD2("*** main process shutdown, processes=%d ***", current_live_processes);
  5727.  
  5728. die_now:
  5729.  
  5730.     tmstart = time(NULL);
  5731.     while (current_live_processes && ((tmstart+60) > time(NULL))) {
  5732.     service_set_status(SERVICE_STOP_PENDING);
  5733.     rv = WaitForMultipleObjects(current_live_processes, (HANDLE *)process_handles, FALSE, 2000);
  5734.     if (rv == WAIT_TIMEOUT)
  5735.         continue;
  5736.     ap_assert(rv != WAIT_FAILED);
  5737.     cld = rv - WAIT_OBJECT_0;
  5738.     ap_assert(rv < current_live_processes);
  5739.     APD4("main_process: child in #%d handle %d died, left=%d", 
  5740.         rv, process_handles[rv], current_live_processes);
  5741.     cleanup_process(process_handles, process_kill_events, cld, ¤t_live_processes);
  5742.     }
  5743.     for (i = 0; i < current_live_processes; i++) {
  5744.     ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, server_conf,
  5745.          "forcing termination of child #%d (handle %d)", i, process_handles[i]);
  5746.     TerminateProcess((HANDLE) process_handles[i], 1);
  5747.     }
  5748.  
  5749.     CloseHandle(signal_restart_event);
  5750.     CloseHandle(signal_shutdown_event);
  5751.  
  5752.     /* cleanup pid file on normal shutdown */
  5753.     {
  5754.     const char *pidfile = NULL;
  5755.     pidfile = ap_server_root_relative (pparent, ap_pid_fname);
  5756.     if ( pidfile != NULL && unlink(pidfile) == 0)
  5757.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
  5758.              server_conf,
  5759.              "removed PID file %s (pid=%ld)",
  5760.              pidfile, (long)getpid());
  5761.     }
  5762.  
  5763.     if (pparent) {
  5764.     ap_destroy_pool(pparent);
  5765.     }
  5766.  
  5767.     ap_destroy_mutex(start_mutex);
  5768.  
  5769.     service_set_status(SERVICE_STOPPED);
  5770.     return (0);
  5771. }
  5772.  
  5773. /*
  5774.  * Send signal to a running Apache. On entry signal should contain
  5775.  * either "shutdown" or "restart"
  5776.  */
  5777.  
  5778. void send_signal(pool *p, char *signal)
  5779. {
  5780.     char prefix[20];
  5781.     FILE *fp;
  5782.     int nread;
  5783.     char *fname;
  5784.     int end;
  5785.  
  5786.     fname = ap_server_root_relative (p, ap_pid_fname);
  5787.  
  5788.     fp = fopen(fname, "r");
  5789.     if (!fp) {
  5790.     printf("Cannot read apache PID file %s\n", fname);
  5791.     return;
  5792.     }
  5793.     prefix[0] = 'a';
  5794.     prefix[1] = 'p';
  5795.  
  5796.     nread = fread(prefix+2, 1, sizeof(prefix)-3, fp);
  5797.     if (nread == 0) {
  5798.     fclose(fp);
  5799.     printf("PID file %s was empty\n", fname);
  5800.     return;
  5801.     }
  5802.     fclose(fp);
  5803.  
  5804.     /* Terminate the prefix string */
  5805.     end = 2 + nread - 1;
  5806.     while (end > 0 && (prefix[end] == '\r' || prefix[end] == '\n'))
  5807.     end--;
  5808.     prefix[end + 1] = '\0';
  5809.  
  5810.     setup_signal_names(prefix);
  5811.  
  5812.     if (!strcasecmp(signal, "shutdown"))
  5813.     ap_start_shutdown();
  5814.     else if (!strcasecmp(signal, "restart"))
  5815.     ap_start_restart(1);
  5816.     else
  5817.     printf("Unknown signal name \"%s\". Use either shutdown or restart.\n",
  5818.         signal);
  5819.  
  5820.     return;
  5821. }
  5822.  
  5823. #ifdef WIN32
  5824. __declspec(dllexport)
  5825.      int apache_main(int argc, char *argv[])
  5826. #else
  5827. int REALMAIN(int argc, char *argv[]) 
  5828. #endif
  5829. {
  5830.     int c;
  5831.     int child = 0;
  5832.     char *cp;
  5833.     int run_as_service = 1;
  5834.     int install = 0;
  5835.     int configtestonly = 0;
  5836.     char *signal_to_send = NULL;
  5837.     char *s;
  5838.     
  5839.     common_init();
  5840.  
  5841.     if ((s = strrchr(argv[0], '/')) != NULL) {
  5842.     ap_server_argv0 = ++s;
  5843.     }
  5844.     else {
  5845.     ap_server_argv0 = argv[0];
  5846.     }
  5847.  
  5848.     /* Get the serverroot from the registry, if it exists. This can be
  5849.      * overridden by a command line -d argument.
  5850.      */
  5851.     if (ap_registry_get_server_root(pconf, ap_server_root, sizeof(ap_server_root)) < 0) {
  5852.     /* The error has already been logged. Actually it won't have been,
  5853.      * because we haven't read the config files to find out where our 
  5854.      * error log is. But we can't just ignore the error since we might
  5855.      * end up using totally the wrong server root.
  5856.      */
  5857.     exit(1);
  5858.     }
  5859.  
  5860.     if (!*ap_server_root) {
  5861.     ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
  5862.     }
  5863.     ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname));
  5864.  
  5865.     ap_setup_prelinked_modules();
  5866.  
  5867.     while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLZ:iusSthk:")) != -1) {
  5868.         char **new;
  5869.     switch (c) {
  5870.     case 'c':
  5871.         new = (char **)ap_push_array(ap_server_post_read_config);
  5872.         *new = ap_pstrdup(pcommands, optarg);
  5873.         break;
  5874.     case 'C':
  5875.         new = (char **)ap_push_array(ap_server_pre_read_config);
  5876.         *new = ap_pstrdup(pcommands, optarg);
  5877.         break;
  5878.     case 'D':
  5879.         new = (char **)ap_push_array(ap_server_config_defines);
  5880.         *new = ap_pstrdup(pcommands, optarg);
  5881.         break;
  5882. #ifdef WIN32
  5883.     case 'Z':
  5884.         exit_event = open_event(optarg);
  5885.         APD2("child: opened process event %s", optarg);
  5886.         cp = strchr(optarg, '_');
  5887.         ap_assert(cp);
  5888.         *cp = 0;
  5889.         setup_signal_names(optarg);
  5890.         start_mutex = ap_open_mutex(signal_name_prefix);
  5891.         ap_assert(start_mutex);
  5892.         child = 1;
  5893.         break;
  5894.     case 'i':
  5895.         install = 1;
  5896.         break;
  5897.     case 'u':
  5898.         install = -1;
  5899.         break;
  5900.     case 's':
  5901.         run_as_service = 0;
  5902.         break;
  5903.     case 'S':
  5904.         ap_dump_settings = 1;
  5905.         break;
  5906.     case 'k':
  5907.         signal_to_send = optarg;
  5908.         break;
  5909. #endif /* WIN32 */
  5910.     case 'd':
  5911.         ap_cpystrn(ap_server_root, ap_os_canonical_filename(pconf, optarg), sizeof(ap_server_root));
  5912.         break;
  5913.     case 'f':
  5914.         ap_cpystrn(ap_server_confname, ap_os_canonical_filename(pconf, optarg), sizeof(ap_server_confname));
  5915.         break;
  5916.     case 'v':
  5917.         ap_set_version();
  5918.         printf("Server version: %s\n", ap_get_server_version());
  5919.         printf("Server built:   %s\n", ap_get_server_built());
  5920.         exit(0);
  5921.     case 'V':
  5922.         ap_set_version();
  5923.         show_compile_settings();
  5924.         exit(0);
  5925.     case 'l':
  5926.         ap_show_modules();
  5927.         exit(0);
  5928.     case 'L':
  5929.         ap_show_directives();
  5930.         exit(0);
  5931.     case 'X':
  5932.         ++one_process;    /* Weird debugging mode. */
  5933.         break;
  5934.     case 't':
  5935.         configtestonly = 1;
  5936.         break;
  5937.     case 'h':
  5938.         usage(argv[0]);
  5939.     case '?':
  5940.         usage(argv[0]);
  5941.     }
  5942.     }
  5943.  
  5944.     if (!child && run_as_service) {
  5945.     service_cd();
  5946.     }
  5947.  
  5948.     server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
  5949.  
  5950.     if (configtestonly) {
  5951.         fprintf(stderr, "Syntax OK\n");
  5952.         exit(0);
  5953.     }
  5954.  
  5955.     if (signal_to_send) {
  5956.     send_signal(pconf, signal_to_send);
  5957.     exit(0);
  5958.     }
  5959.  
  5960.     if (!child && !ap_dump_settings && !install) {
  5961.     ap_log_pid(pconf, ap_pid_fname);
  5962.     }
  5963.     ap_set_version();
  5964.     ap_init_modules(pconf, server_conf);
  5965.     ap_suexec_enabled = init_suexec();
  5966.     version_locked++;
  5967.     ap_open_logs(server_conf, pconf);
  5968.     set_group_privs();
  5969.  
  5970. #ifdef OS2
  5971.     printf("%s running...\n", ap_get_server_version());
  5972. #endif
  5973. #ifdef WIN32
  5974.     if (!child) {
  5975.     printf("%s running...\n", ap_get_server_version());
  5976.     }
  5977. #endif
  5978.  
  5979.     if (one_process && !exit_event)
  5980.     exit_event = create_event(0, 0, NULL);
  5981.     if (one_process && !start_mutex)
  5982.     start_mutex = ap_create_mutex(NULL);
  5983.     /*
  5984.      * In the future, the main will spawn off a couple
  5985.      * of children and monitor them. As soon as a child
  5986.      * exits, it spawns off a new one
  5987.      */
  5988.     if (child || one_process) {
  5989.     if (!exit_event || !start_mutex)
  5990.         exit(-1);
  5991.     worker_main();
  5992.     ap_destroy_mutex(start_mutex);
  5993.     destroy_event(exit_event);
  5994.     }
  5995.     else {
  5996.     service_main(master_main, argc, argv,
  5997.             "Apache", install, run_as_service);
  5998.     }
  5999.  
  6000.     clean_parent_exit(0);
  6001.     return 0;    /* purely to avoid a warning */
  6002. }
  6003.  
  6004. #endif /* ndef MULTITHREAD */
  6005.  
  6006. #else  /* ndef SHARED_CORE_TIESTATIC */
  6007.  
  6008. /*
  6009. **  Standalone Tie Program for Shared Core support
  6010. **
  6011. **  It's purpose is to tie the static libraries and 
  6012. **  the shared core library under link-time and  
  6013. **  passing execution control to the real main function
  6014. **  in the shared core library under run-time.
  6015. */
  6016.  
  6017. extern int ap_main(int argc, char *argv[]);
  6018.  
  6019. int main(int argc, char *argv[]) 
  6020. {
  6021.     return ap_main(argc, argv);
  6022. }
  6023.  
  6024. #endif /* ndef SHARED_CORE_TIESTATIC */
  6025. #else  /* ndef SHARED_CORE_BOOTSTRAP */
  6026.  
  6027. /*
  6028. **  Standalone Bootstrap Program for Shared Core support
  6029. **
  6030. **  It's purpose is to initialise the LD_LIBRARY_PATH
  6031. **  environment variable therewith the Unix loader is able
  6032. **  to start the Standalone Tie Program (see above)
  6033. **  and then replacing itself with this program by
  6034. **  immediately passing execution to it.
  6035. */
  6036.  
  6037. #include <stdio.h>
  6038. #include <stdlib.h>
  6039. #include <string.h>
  6040.  
  6041. #include "ap_config.h"
  6042. #include "httpd.h"
  6043.  
  6044. #if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
  6045. #define VARNAME "SHLIB_PATH"
  6046. #else
  6047. #define VARNAME "LD_LIBRARY_PATH"
  6048. #endif
  6049.  
  6050. #ifndef SHARED_CORE_DIR 
  6051. #define SHARED_CORE_DIR HTTPD_ROOT "/libexec"
  6052. #endif
  6053.  
  6054. #ifndef SHARED_CORE_EXECUTABLE_PROGRAM
  6055. #define SHARED_CORE_EXECUTABLE_PROGRAM "lib" TARGET ".ep"
  6056. #endif
  6057.  
  6058. extern char *optarg;
  6059. extern int   optind;
  6060.  
  6061. int main(int argc, char *argv[], char *envp[]) 
  6062. {
  6063.     char prog[MAX_STRING_LEN];
  6064.     char llp_buf[MAX_STRING_LEN];
  6065.     char **llp_slot;
  6066.     char *llp_existing;
  6067.     char *llp_dir;
  6068.     char **envpnew;
  6069.     int c, i, l;
  6070.  
  6071.     /* 
  6072.      * parse argument line, 
  6073.      * but only handle the -L option 
  6074.      */
  6075.     llp_dir = SHARED_CORE_DIR;
  6076.     while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:th")) != -1) {
  6077.     switch (c) {
  6078.     case 'D':
  6079.     case 'C':
  6080.     case 'c':
  6081.     case 'X':
  6082.     case 'd':
  6083.     case 'f':
  6084.     case 'v':
  6085.     case 'V':
  6086.     case 'l':
  6087.     case 'L':
  6088.     case 'S':
  6089.     case 'Z':
  6090.     case 't':
  6091.     case 'h':
  6092.     case '?':
  6093.         break;
  6094.     case 'R':
  6095.         llp_dir = strdup(optarg);
  6096.         break;
  6097.     }
  6098.     }
  6099.  
  6100.     /* 
  6101.      * create path to SHARED_CORE_EXECUTABLE_PROGRAM
  6102.      */
  6103.     sprintf(prog, "%s/%s", llp_dir, SHARED_CORE_EXECUTABLE_PROGRAM);
  6104.  
  6105.     /* 
  6106.      * adjust process environment therewith the Unix loader 
  6107.      * is able to start the SHARED_CORE_EXECUTABLE_PROGRAM.
  6108.      */
  6109.     llp_slot = NULL;
  6110.     llp_existing = NULL;
  6111.     l = strlen(VARNAME);
  6112.     for (i = 0; envp[i] != NULL; i++) {
  6113.     if (strncmp(envp[i], VARNAME "=", l+1) == 0) {
  6114.         llp_slot = &envp[i];
  6115.         llp_existing = strchr(envp[i], '=') + 1;
  6116.     }
  6117.     }
  6118.     if (llp_slot == NULL) {
  6119.     envpnew = (char **)malloc(sizeof(char *)*(i + 2));
  6120.     memcpy(envpnew, envp, sizeof(char *)*i);
  6121.     envp = envpnew;
  6122.     llp_slot = &envp[i++];
  6123.     envp[i] = NULL;
  6124.     }
  6125.     if (llp_existing != NULL)
  6126.      sprintf(llp_buf, "%s=%s:%s", VARNAME, llp_dir, llp_existing);
  6127.     else
  6128.      sprintf(llp_buf, "%s=%s", VARNAME, llp_dir);
  6129.     *llp_slot = strdup(llp_buf);
  6130.  
  6131.     /* 
  6132.      * finally replace our process with 
  6133.      * the SHARED_CORE_EXECUTABLE_PROGRAM
  6134.      */
  6135.     if (execve(prog, argv, envp) == -1) {
  6136.     fprintf(stderr, 
  6137.         "%s: Unable to exec Shared Core Executable Program `%s'\n",
  6138.         argv[0], prog);
  6139.     return 1;
  6140.     }
  6141.     else
  6142.     return 0;
  6143. }
  6144.  
  6145. #endif /* ndef SHARED_CORE_BOOTSTRAP */
  6146.  
  6147.