--- server/mpm/prefork/prefork.c 2008-11-03 20:59:08.000000000 +0100 +++ server/mpm/prefork/prefork.c 2008-11-03 20:59:01.362558019 +0100 @@ -102,6 +102,8 @@ static int changed_limit_at_restart; static int mpm_state = AP_MPMQ_STARTING; static ap_pod_t *pod; +static int dummy_listener; + /* * The max child slot ever assigned, preserved across restarts. Necessary * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We @@ -139,6 +141,8 @@ char tpf_server_name[INETD_SERVNAME_LENG #endif /* TPF */ static volatile int die_now = 0; +static volatile int listeners_closed = 0; +static int active_connection = 0; #ifdef GPROF /* @@ -330,7 +334,18 @@ static void just_die(int sig) static void stop_listening(int sig) { - ap_close_listeners(); + if (active_connection) { + ap_listen_rec *lr; + + for (lr = ap_listeners; lr; lr = lr->next) { + apr_os_sock_t fd; + + apr_os_sock_get(&fd, lr->sd); + + dup2(dummy_listener, fd); + } + listeners_closed = 1; + } /* For a graceful stop, we want the child to exit when done */ die_now = 1; @@ -573,6 +588,11 @@ static void child_main(int child_num_arg apr_int32_t numdesc; const apr_pollfd_t *pdesc; + if (die_now) { + status = !APR_SUCCESS; + goto unlock; + } + /* timeout == -1 == wait forever */ status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc); if (status != APR_SUCCESS) { @@ -628,8 +648,14 @@ static void child_main(int child_num_arg /* if we accept() something we don't want to die, so we have to * defer the exit */ - status = lr->accept_func(&csd, lr, ptrans); + if (!die_now) { + status = lr->accept_func(&csd, lr, ptrans); + } + else { + status = !APR_SUCCESS; + } + unlock: SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */ if (status == APR_EGENERAL) { @@ -645,11 +671,18 @@ static void child_main(int child_num_arg * socket options, file descriptors, and read/write buffers. */ + active_connection = 1; + if (die_now && !listeners_closed) { + ap_close_listeners(); + listeners_closed = 1; + } + current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc); if (current_conn) { ap_process_connection(current_conn, csd); ap_lingering_close(current_conn); } + active_connection = 0; /* Check the pod and the generation number after processing a * connection so that we'll go away if a graceful restart occurred @@ -916,6 +949,17 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p "ignored during restart"); changed_limit_at_restart = 0; } + + if (dummy_listener == 0) { + dummy_listener = socket(AF_INET, SOCK_STREAM, 0); + if (dummy_listener < 0) { + rv = errno; + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, + "Couldn't create dummy listener socket"); + mpm_state = AP_MPMQ_STOPPING; + return 1; + } + } /* Initialize cross-process accept lock */ ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT,