mpm_winnt.c revision 1ce78cf71b5baaf2c1ab48e818cb1f2397df5010
2d2eda71267231c2526be701fe655db125852c1ffielding/* Licensed to the Apache Software Foundation (ASF) under one or more
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * contributor license agreements. See the NOTICE file distributed with
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * this work for additional information regarding copyright ownership.
bc8fd1b0b1afdf89b8d28eefa8cd74e26ba97986fielding * The ASF licenses this file to You under the Apache License, Version 2.0
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * (the "License"); you may not use this file except in compliance with
2d2eda71267231c2526be701fe655db125852c1ffielding * the License. You may obtain a copy of the License at
2d2eda71267231c2526be701fe655db125852c1ffielding * Unless required by applicable law or agreed to in writing, software
2d2eda71267231c2526be701fe655db125852c1ffielding * distributed under the License is distributed on an "AS IS" BASIS,
2d2eda71267231c2526be701fe655db125852c1ffielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2d2eda71267231c2526be701fe655db125852c1ffielding * See the License for the specific language governing permissions and
2d2eda71267231c2526be701fe655db125852c1ffielding * limitations under the License.
f062ed7bd262a37a909dd77ce5fc23b446818823fielding/* scoreboard.c does the heavy lifting; all we do is create the child
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * score by moving a handle down the pipe into the child's stdin.
2d2eda71267231c2526be701fe655db125852c1ffielding/* Definitions of WINNT MPM specific config globals */
f062ed7bd262a37a909dd77ce5fc23b446818823fieldingstatic HANDLE shutdown_event; /* used to signal the parent to shutdown */
f062ed7bd262a37a909dd77ce5fc23b446818823fieldingstatic HANDLE restart_event; /* used to signal the parent to restart */
f062ed7bd262a37a909dd77ce5fc23b446818823fieldingstatic int one_process = 0;
92f3af936ce61f25358a3ee4f28df2f6d62040dfdreidstatic int thread_limit = 0;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbbstatic int first_thread_limit = 0;
2d2eda71267231c2526be701fe655db125852c1ffielding/* ap_my_generation are used by the scoreboard code */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* shared by service.c as global, although
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * perhaps it should be private.
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb/* definitions from child.c */
2d2eda71267231c2526be701fe655db125852c1ffielding/* used by parent to signal the child to start and exit
2d2eda71267231c2526be701fe655db125852c1ffielding * NOTE: these are not sophisticated enough for multiple children
2d2eda71267231c2526be701fe655db125852c1ffielding * so they ultimately should not be shared with child.c
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* Stub functions until this MPM supports the connection status API */
2d2eda71267231c2526be701fe655db125852c1ffieldingAP_DECLARE(void) ap_update_connection_status(long conn_id, const char *key, \
2d2eda71267231c2526be701fe655db125852c1ffielding const char *value)
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianpAP_DECLARE(void) ap_reset_connection_status(long conn_id)
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianpAP_DECLARE(apr_array_header_t *) ap_get_status_table(apr_pool_t *p)
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb * Command processors
61fd0cab072a05b855cbef9c585702401ac5ae29rbbstatic const char *set_threads_per_child (cmd_parms *cmd, void *dummy, char *arg)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
61fd0cab072a05b855cbef9c585702401ac5ae29rbbstatic const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *arg)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2d2eda71267231c2526be701fe655db125852c1ffieldingstatic const char *set_disable_acceptex(cmd_parms *cmd, void *dummy, char *arg)
2d2eda71267231c2526be701fe655db125852c1ffielding const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein "Disabled use of AcceptEx() WinSock2 API");
61fd0cab072a05b855cbef9c585702401ac5ae29rbbAP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Number of threads each child creates" ),
61fd0cab072a05b855cbef9c585702401ac5ae29rbbAP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe "Maximum worker threads in a server for this run of Apache"),
7bdef86e15d47d16dcbe7a5611683191774bd5fbgsteinAP_INIT_NO_ARGS("Win32DisableAcceptEx", set_disable_acceptex, NULL, RSRC_CONF,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Disable use of the high performance AcceptEx WinSock2 API to work around buggy VPN or Firewall software"),
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * Signalling Apache on NT.
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein * Under Unix, Apache can be told to shutdown or restart by sending various
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * signals (HUP, USR, TERM). On NT we don't have easy access to signals, so
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * we use "events" instead. The parent apache process goes into a loop
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * where it waits forever for a set of events. Two of those events are
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * apPID_shutdown
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * apPID_restart
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * (where PID is the PID of the apache parent process). When one of these
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * is signalled, the Apache parent performs the appropriate action. The events
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * can become signalled through internal Apache methods (e.g. if the child
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * finds a fatal error and needs to kill its parent), via the service
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * control manager (the control thread will signal the shutdown event when
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * requested to stop the Apache service), from the -k Apache command line,
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * or from any external program which finds the Apache PID from the
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * httpd.pid file.
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * The signal_parent() function, below, is used to signal one of these events.
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * It can be called by any child or parent process, since it does not
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * rely on global variables.
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * On entry, type gives the event to signal. 0 means shutdown, 1 means
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * graceful restart.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * Initialise the signal names, in the global variables signal_name_prefix,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * signal_restart_name and signal_shutdown_name.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#define MAX_SIGNAL_NAME 30 /* Long enough for apPID_shutdown, where PID is an int */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_snprintf(signal_name_prefix, sizeof(signal_name_prefix), prefix);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_snprintf(signal_shutdown_name, sizeof(signal_shutdown_name),
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_snprintf(signal_restart_name, sizeof(signal_restart_name),
61fd0cab072a05b855cbef9c585702401ac5ae29rbbint volatile is_graceful = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbbAP_DECLARE(void) ap_signal_parent(ap_signal_parent_e type)
2d2eda71267231c2526be701fe655db125852c1ffielding /* This MPM supports only graceful restarts right now */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* This MPM supports only graceful restarts right now */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe /* Um, problem, can't signal the parent, which means we can't
2d2eda71267231c2526be701fe655db125852c1ffielding * signal ourselves to die. Ignore for now...
2d2eda71267231c2526be701fe655db125852c1ffielding ap_log_error(APLOG_MARK, APLOG_EMERG, apr_get_os_error(), ap_server_conf,
62db15de4c1f335a64d45821796ae197cff94ef8rbb if (SetEvent(e) == 0) {
62db15de4c1f335a64d45821796ae197cff94ef8rbb /* Same problem as above */
62db15de4c1f335a64d45821796ae197cff94ef8rbb ap_log_error(APLOG_MARK, APLOG_EMERG, apr_get_os_error(), ap_server_conf,
62db15de4c1f335a64d45821796ae197cff94ef8rbb * Passed the following handles [in sync with send_handles_to_child()]
62db15de4c1f335a64d45821796ae197cff94ef8rbb * ready event [signal the parent immediately, then close]
62db15de4c1f335a64d45821796ae197cff94ef8rbb * exit event [save to poll later]
62db15de4c1f335a64d45821796ae197cff94ef8rbb * start mutex [signal from the parent to begin accept()]
62db15de4c1f335a64d45821796ae197cff94ef8rbb * scoreboard shm handle [to recreate the ap_scoreboard]
48d2edbfb84e5559b5da0f8d614ccab805cc67a8rbbvoid get_handles_from_parent(server_rec *s, HANDLE *child_exit_event,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
a19698aebe10b9d41574e4a73794ba7d4cecd78btrawick "Child %d: Unable to retrieve the ready event from the parent", my_pid);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "Child %d: Unable to retrieve the exit event from the parent", my_pid);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "Child %d: Unable to retrieve the start_mutex from the parent", my_pid);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if ((rv = apr_os_proc_mutex_put(child_start_mutex, &os_start, s->process->pool))
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "Child %d: Unable to access the start_mutex from the parent", my_pid);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "Child %d: Unable to retrieve the scoreboard from the parent", my_pid);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if ((rv = apr_os_shm_put(scoreboard_shm, &hScore, s->process->pool))
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "Child %d: Unable to access the scoreboard from the parent", my_pid);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar rv = ap_reopen_scoreboard(s->process->pool, scoreboard_shm, 1);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (rv || !(sb_shared = apr_shm_baseaddr_get(*scoreboard_shm))) {
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "Child %d: Unable to reopen the scoreboard from the parent", my_pid);
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard /* We must 'initialize' the scoreboard to relink all the
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard * process-local pointer arrays into the shared memory block.
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
2864362ca8266097928e84f101010bdf814ffa08stoddard "Child %d: Retrieved our scoreboard from the parent.", my_pid);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (!DuplicateHandle(hCurrentProcess, child_ready_event, hProcess, &hDup,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Unable to duplicate the ready event handle for the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((rv = apr_file_write_full(child_in, &hDup, sizeof(hDup), &BytesWritten))
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Unable to send the exit event handle to the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (!DuplicateHandle(hCurrentProcess, child_exit_event, hProcess, &hDup,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein "Parent: Unable to duplicate the exit event handle for the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((rv = apr_file_write_full(child_in, &hDup, sizeof(hDup), &BytesWritten))
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Unable to send the exit event handle to the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein if ((rv = apr_os_proc_mutex_get(&os_start, child_start_mutex)) != APR_SUCCESS) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Unable to retrieve the start mutex for the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (!DuplicateHandle(hCurrentProcess, os_start, hProcess, &hDup,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Unable to duplicate the start mutex to the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((rv = apr_file_write_full(child_in, &hDup, sizeof(hDup), &BytesWritten))
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Unable to send the start mutex to the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((rv = apr_os_shm_get(&hScore, scoreboard_shm)) != APR_SUCCESS) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe "Parent: Unable to retrieve the scoreboard handle for the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (!DuplicateHandle(hCurrentProcess, hScore, hProcess, &hDup,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Unable to duplicate the scoreboard handle to the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
2d2eda71267231c2526be701fe655db125852c1ffielding if ((rv = apr_file_write_full(child_in, &hDup, sizeof(hDup), &BytesWritten))
2d2eda71267231c2526be701fe655db125852c1ffielding ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
2d2eda71267231c2526be701fe655db125852c1ffielding "Parent: Unable to send the scoreboard handle to the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
2d2eda71267231c2526be701fe655db125852c1ffielding ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe "Parent: Sent the scoreboard to the child");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * get_listeners_from_parent()
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * The listen sockets are opened in the parent. This function, which runs
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * exclusively in the child process, receives them from the parent and
d839a9822ee53ce00da24c15f2d9fe054233d342gstein * makes them availeble in the child.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* Set up a default listener if necessary */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb lr = apr_palloc(s->process->pool, sizeof(ap_listen_rec));
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* Open the pipe to the parent process to receive the inherited socket
face099b681c052cb1f52176a5499661c44b2982trawick * data. The sockets have been set to listening in the parent process.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (!ReadFile(pipe, &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO),
3d96ee83babeec32482c9082c9426340cee8c44dwrowe ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein "setup_inherited_listeners: Unable to read socket data from parent");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb nsd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Child %d: setup_inherited_listeners(), WSASocket failed to open the inherited socket.", my_pid);
11a7b0dff22d26770b532c174d1cf2e7b56ec244wrowe if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (DuplicateHandle(hProcess, (HANDLE) nsd, hProcess, &dup,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* A different approach. Many users report errors such as
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * (32538)An operation was attempted on something that is not
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * a socket. : Parent: WSADuplicateSocket failed...
2d2eda71267231c2526be701fe655db125852c1ffielding * This appears that the duplicated handle is no longer recognized
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein * as a socket handle. SetHandleInformation should overcome that
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * problem by not altering the handle identifier. But this won't
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * work on 9x - it's unsupported.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (!SetHandleInformation((HANDLE)nsd, HANDLE_FLAG_INHERIT, 0)) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "set_listeners_noninheritable: SetHandleInformation failed.");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Child %d: retrieved %d listeners from parent", my_pid, lcnt);
3d96ee83babeec32482c9082c9426340cee8c44dwrowestatic int send_listeners_to_child(apr_pool_t *p, DWORD dwProcessId,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe /* Run the chain of open sockets. For each socket, duplicate it
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein * for the target process then send the WSAPROTOCOL_INFO
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * (returned by dup socket) to the child.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb lpWSAProtocolInfo = apr_pcalloc(p, sizeof(WSAPROTOCOL_INFO));
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Duplicating socket %d and sending it to child process %d",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: WSADuplicateSocket failed for socket %d. Check the FAQ.", lr->sd );
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((rv = apr_file_write_full(child_in, lpWSAProtocolInfo,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Unable to write duplicated socket %d to the child.", lr->sd );
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe "Parent: Sent %d listeners to child %d", lcnt, dwProcessId);
fd8b91502bc200ed4cca3810560a2a570522b3debrianpstatic int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_event,
fd8b91502bc200ed4cca3810560a2a570522b3debrianp /* These NEVER change for the lifetime of this parent
fd8b91502bc200ed4cca3810560a2a570522b3debrianp /* Build the command line. Should look something like this:
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp * C:/apache/bin/apache.exe -f ap_server_confname
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz * First, get the path to the executable...
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames if (((rv = apr_filepath_get(&cwd, 0, ptemp)) != APR_SUCCESS)
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames || ((rv = apr_procattr_dir_set(attr, cwd)) != APR_SUCCESS)) {
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp "Parent: Failed to get the current path");
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames /* Build the args array, only once since it won't change
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames * for the lifetime of this parent process.
5a9667916c79d8c699b069068e5570aa1c331c80gstein ap_log_error(APLOG_MARK, APLOG_CRIT, ERROR_BAD_PATHNAME, ap_server_conf,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Parent: Failed to get full path of %s",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe args = malloc((ap_server_conf->process->argc + 1) * sizeof (char*));
2d2eda71267231c2526be701fe655db125852c1ffielding memcpy(args + 1, ap_server_conf->process->argv + 1,
d5df46b7972c0c4a5ca0ba5068e238f6053c2e6ftrawick /* Create a pipe to send handles to the child */
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding if ((rv = apr_procattr_io_set(attr, APR_FULL_BLOCK,
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding "Parent: Unable to create child stdin pipe.");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* Open a null handle to soak info from the child */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (((rv = apr_file_open(&child_out, "NUL", APR_READ | APR_WRITE,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb || ((rv = apr_procattr_child_out_set(attr, child_out, NULL))
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein "Parent: Unable to connect child stdout to NUL.");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* Connect the child's initial stderr to our main server error log
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * or share our own stderr handle.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((rv = apr_procattr_child_err_set(attr, child_err, NULL))
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein "Parent: Unable to connect child stderr.");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return -1;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* Create the child_ready_event */
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm waitlist[waitlist_ready] = CreateEvent(NULL, TRUE, FALSE, NULL);
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein "Parent: Could not create ready event for child process");
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb return -1;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb /* Create the child_exit_event */
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
0de8f88b22d24dd57ed10b96fb594e69b6aa0072jwoolley "Parent: Could not create exit event for child process");
8b7047e519340545e6807c9749576a40a76b6d3frbb return -1;
9484ae61c7cc5fa8d8d9a836efdbdb1e88d3036dwrowe /* Build the env array, only once since it won't change
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb * for the lifetime of this parent process.
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb apr_snprintf(pidbuf, sizeof(pidbuf), "AP_PARENT_PID=%i", parent_pid);
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb rv = apr_proc_create(&new_child, cmd, args, env, attr, ptemp);
561e5f16a2f9fb397aac4c283aaa87a752520a4ddougm ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb "Parent: Failed to create the child process.");
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb return -1;
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf,
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley "Parent: Created child process %d", new_child.pid);
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley if (send_handles_to_child(ptemp, waitlist[waitlist_ready], hExitEvent,
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley * This error is fatal, mop up the child and move on
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb * We toggle the child's exit event to cause this child
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * to quit even as it is attempting to start.
c9a95767fbf0f5fb0976a06b97a256033925e433rbb return -1;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb /* Important:
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * Give the child process a chance to run before dup'ing the sockets.
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * We have already set the listening sockets noninheritable, but if
2d2eda71267231c2526be701fe655db125852c1ffielding * WSADuplicateSocket runs before the child process initializes
2d2eda71267231c2526be701fe655db125852c1ffielding * the listeners will be inherited anyway.
2d2eda71267231c2526be701fe655db125852c1ffielding rv = WaitForMultipleObjects(2, waitlist, FALSE, INFINITE);
* call by code in service.c.
* call by code in service.c.
#define CHILD_HANDLE 0
int restart_pending;
int shutdown_pending;
if (rv < 0)
goto die_now;
for (i = 0; i < ap_threads_per_child; i++) {
if (restart_pending) {
if (shutdown_pending)
switch(query_code){
case AP_MPMQ_MAX_DAEMON_USED:
return APR_SUCCESS;
case AP_MPMQ_IS_THREADED:
return APR_SUCCESS;
case AP_MPMQ_IS_FORKED:
return APR_SUCCESS;
return APR_SUCCESS;
return APR_SUCCESS;
case AP_MPMQ_MAX_THREADS:
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
return APR_SUCCESS;
case AP_MPMQ_MAX_DAEMONS:
*result = 0;
return APR_SUCCESS;
case AP_MPMQ_MPM_STATE:
return APR_SUCCESS;
return APR_ENOTIMPL;
static int inst_argc;
static const char * const *inst_argv;
char *def_server_root;
char *binpath;
const char *optarg;
int fixed_args;
char *pid;
int errout = 0;
if (pid)
ap_real_exit_code = 0;
!= APR_SUCCESS) {
if (ap_real_exit_code)
optarg);
if (optarg) {
if (!signal_arg)
running_as_service = 0;
if (!errout) {
else if (running_as_service)
exit(0);
use_acceptex = 0;
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
use_acceptex = 0;
return OK;
int is_parent;
static int restart_num = 0;
int startup = 0;
if (startup) {
} else if (is_parent) {
if (startup) {
} else if (is_parent) {
if (!first_thread_limit) {
if (is_parent) {
if (startup) {
} else if (is_parent) {
if (startup) {
} else if (is_parent) {
return OK;
static int restart_num = 0;
* is a valid conf\httpd.conf environment to start.
exit(0);
exit(0);
if (!shutdown_event) {
return HTTP_INTERNAL_SERVER_ERROR;
if (!restart_event) {
return HTTP_INTERNAL_SERVER_ERROR;
return HTTP_INTERNAL_SERVER_ERROR;
return HTTP_INTERNAL_SERVER_ERROR;
return OK;
ap_server_conf = s;
return OK;
return OK;
return DONE;
return OK;
if (!one_process) {
if (!restart)