Commit eb99f1c7 authored by Yann Ylavic's avatar Yann Ylavic
Browse files

Merge r1809881, r1809973, r1809976, r1812075 from trunk:

core: deregister all hooks before leaving pconf, otherwise some late cleanup
or function call (e.g. ap_log) may use one while DSOs are unloaded.

See PR 61558 (double/second fault).


core, MPMs unix: follow up to r1809881.

Deregister all hooks first (in pre_cleanup), by doing it last we could still
have had them run when DSOs were unloaded.

Likewise, avoid double faults when handling fatal signals by restoring the
default handler before pconf is cleared (we can't ap_log_error there).

Finally, we need to ignore sig_term/restart (do nothing) when the main
process is exiting (i.e. ap_pglobal is destroyed), since retained_data are
freed.

Aimed to fix all faults in PR 61558.


MPMs unix: follow up to r1809881 and r1809973.

unset_signals() is called when ap_pglobal is destroyed too.


Follow up to r1809881: CHANGES entry.


Reviewed by: ylavic, jim, covener


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1820794 13f79535-47bb-0310-9956-ffa450edef68
parent 5f49cf3e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
                                                         -*- coding: utf-8 -*-
Changes with Apache 2.4.30
 
  *) core: A signal received while stopping could have crashed the main
     process.  PR 61558.  [Yann Ylavic]

  *) mod_ssl: support for mod_md added. [Stefan Eissing]
  
  *) mod_proxy_html: process parsed comments immediately. 
+24 −0
Original line number Diff line number Diff line
@@ -437,11 +437,19 @@ AP_DECLARE(apr_status_t) ap_unixd_accept(void **accepted, ap_listen_rec *lr,
/* Unixes MPMs' */

static ap_unixd_mpm_retained_data *retained_data = NULL;
static apr_status_t retained_data_cleanup(void *unused)
{
    (void)unused;
    retained_data = NULL;
    return APR_SUCCESS;
}

AP_DECLARE(ap_unixd_mpm_retained_data *) ap_unixd_mpm_get_retained_data()
{
    if (!retained_data) {
        retained_data = ap_retained_data_create("ap_unixd_mpm_retained_data",
                                                sizeof(*retained_data));
        apr_pool_pre_cleanup_register(ap_pglobal, NULL, retained_data_cleanup);
        retained_data->mpm_state = AP_MPMQ_STARTING;
    }
    return retained_data;
@@ -449,6 +457,10 @@ AP_DECLARE(ap_unixd_mpm_retained_data *) ap_unixd_mpm_get_retained_data()

static void sig_term(int sig)
{
    if (!retained_data) {
        /* Main process (ap_pglobal) is dying */
        return;
    }
    retained_data->mpm_state = AP_MPMQ_STOPPING;
    if (retained_data->shutdown_pending
            && (retained_data->is_ungraceful
@@ -465,6 +477,10 @@ static void sig_term(int sig)

static void sig_restart(int sig)
{
    if (!retained_data) {
        /* Main process (ap_pglobal) is dying */
        return;
    }
    retained_data->mpm_state = AP_MPMQ_STOPPING;
    if (retained_data->restart_pending
            && (retained_data->is_ungraceful
@@ -481,6 +497,10 @@ static void sig_restart(int sig)

static apr_status_t unset_signals(void *unused)
{
    if (!retained_data) {
        /* Main process (ap_pglobal) is dying */
        return APR_SUCCESS;
    }
    retained_data->shutdown_pending = retained_data->restart_pending = 0;
    retained_data->was_graceful = !retained_data->is_ungraceful;
    retained_data->is_ungraceful = 0;
@@ -494,6 +514,10 @@ AP_DECLARE(void) ap_unixd_mpm_set_signals(apr_pool_t *pconf, int one_process)
    struct sigaction sa;
#endif

    if (!one_process) {
        ap_fatal_signal_setup(ap_server_conf, pconf);
    }

    /* Signals' handlers depend on retained data */
    (void)ap_unixd_mpm_get_retained_data();

+28 −5
Original line number Diff line number Diff line
@@ -273,6 +273,30 @@ static int abort_on_oom(int retcode)
    return retcode; /* unreachable, hopefully. */
}

/* Deregister all hooks when clearing pconf (pre_cleanup).
 * TODO: have a hook to deregister and run them from here?
 *       ap_clear_auth_internal() is already a candidate.
 */
static apr_status_t deregister_all_hooks(void *unused)
{
    (void)unused;
    ap_clear_auth_internal();
    apr_hook_deregister_all();
    return APR_SUCCESS;
}

static void reset_process_pconf(process_rec *process)
{
    if (process->pconf) {
        apr_pool_clear(process->pconf);
    }
    else {
        apr_pool_create(&process->pconf, process->pool);
        apr_pool_tag(process->pconf, "pconf");
    }
    apr_pool_pre_cleanup_register(process->pconf, NULL, deregister_all_hooks);
}

static process_rec *init_process(int *argc, const char * const * *argv)
{
    process_rec *process;
@@ -317,8 +341,9 @@ static process_rec *init_process(int *argc, const char * const * *argv)
    process = apr_palloc(cntx, sizeof(process_rec));
    process->pool = cntx;

    apr_pool_create(&process->pconf, process->pool);
    apr_pool_tag(process->pconf, "pconf");
    process->pconf = NULL;
    reset_process_pconf(process);

    process->argc = *argc;
    process->argv = *argv;
    process->short_name = apr_filepath_name_get((*argv)[0]);
@@ -721,9 +746,7 @@ int main(int argc, const char * const argv[])

    do {
        ap_main_state = AP_SQ_MS_DESTROY_CONFIG;
        apr_hook_deregister_all();
        apr_pool_clear(pconf);
        ap_clear_auth_internal();
        reset_process_pconf(process);

        ap_main_state = AP_SQ_MS_CREATE_CONFIG;
        ap_config_generation++;
+0 −3
Original line number Diff line number Diff line
@@ -2878,9 +2878,6 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
        ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
    }

    if (!one_process) {
        ap_fatal_signal_setup(ap_server_conf, pconf);
    }
    ap_unixd_mpm_set_signals(pconf, one_process);

    /* Don't thrash since num_buckets depends on the
+0 −3
Original line number Diff line number Diff line
@@ -863,9 +863,6 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
        ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
    }

    if (!one_process) {
        ap_fatal_signal_setup(ap_server_conf, pconf);
    }
    ap_unixd_mpm_set_signals(pconf, one_process);

    if (one_process) {
Loading