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

Merge r1783849 from trunk:

MPMs unix: Place signals handlers and helpers out of DSOs to avoid
a possible crash if a signal is caught during (graceful) restart.
PR 60487.

Reviewedby: ylavic, wrowe, icing


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1797368 13f79535-47bb-0310-9956-ffa450edef68
parent 06974b86
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2,6 +2,10 @@

Changes with Apache 2.4.26

  *) MPMs unix: Place signals handlers and helpers out of DSOs to avoid
     a possible crash if a signal is caught during (graceful) restart.
     PR 60487.  [Yann Ylavic]

  *) core: Deprecate ap_get_basic_auth_pw() and add
     ap_get_basic_auth_components().
     [Emmanuel Dreyfus <manu netbsd.org>, Jacob Champion, Eric Covener]
+0 −7
Original line number Diff line number Diff line
@@ -120,13 +120,6 @@ RELEASE SHOWSTOPPERS:
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
  [ start all new proposals below, under PATCHES PROPOSED. ]

  *) MPMs unix: Place signals handlers and helpers out of DSOs to avoid a
     possible crash if a signal is caught during (graceful) restart. PR 60487.
     trunk patch: http://svn.apache.org/r1783849
     2.4.x patch: svn merge -c 1783849 ^/httpd/httpd/trunk .
                  (trunk works, modulo CHANGES)
     +1: ylavic, wrowe, icing

PATCHES PROPOSED TO BACKPORT FROM TRUNK:
  [ New proposals should be added at the end of the list ]

+149 −0
Original line number Diff line number Diff line
@@ -434,6 +434,155 @@ 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;
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));
        retained_data->mpm_state = AP_MPMQ_STARTING;
    }
    return retained_data;
}

static void sig_term(int sig)
{
    retained_data->mpm_state = AP_MPMQ_STOPPING;
    if (retained_data->shutdown_pending
            && (retained_data->is_ungraceful
                || sig == AP_SIG_GRACEFUL_STOP)) {
        /* Already handled */
        return;
    }

    retained_data->shutdown_pending = 1;
    if (sig != AP_SIG_GRACEFUL_STOP) {
        retained_data->is_ungraceful = 1;
    }
}

static void sig_restart(int sig)
{
    retained_data->mpm_state = AP_MPMQ_STOPPING;
    if (retained_data->restart_pending
            && (retained_data->is_ungraceful
                || sig == AP_SIG_GRACEFUL)) {
        /* Already handled */
        return;
    }

    retained_data->restart_pending = 1;
    if (sig != AP_SIG_GRACEFUL) {
        retained_data->is_ungraceful = 1;
    }
}

static apr_status_t unset_signals(void *unused)
{
    retained_data->shutdown_pending = retained_data->restart_pending = 0;
    retained_data->was_graceful = !retained_data->is_ungraceful;
    retained_data->is_ungraceful = 0;

    return APR_SUCCESS;
}

AP_DECLARE(void) ap_unixd_mpm_set_signals(apr_pool_t *pconf, int one_process)
{
#ifndef NO_USE_SIGACTION
    struct sigaction sa;
#endif

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

#ifndef NO_USE_SIGACTION
    memset(&sa, 0, sizeof sa);
    sigemptyset(&sa.sa_mask);

#ifdef SIGPIPE
    sa.sa_handler = SIG_IGN;
    if (sigaction(SIGPIPE, &sa, NULL) < 0)
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00269)
                     "sigaction(SIGPIPE)");
#endif
#ifdef SIGXCPU
    sa.sa_handler = SIG_DFL;
    if (sigaction(SIGXCPU, &sa, NULL) < 0)
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00267)
                     "sigaction(SIGXCPU)");
#endif
#ifdef SIGXFSZ
    /* For systems following the LFS standard, ignoring SIGXFSZ allows
     * a write() beyond the 2GB limit to fail gracefully with E2BIG
     * rather than terminate the process. */
    sa.sa_handler = SIG_IGN;
    if (sigaction(SIGXFSZ, &sa, NULL) < 0)
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00268)
                     "sigaction(SIGXFSZ)");
#endif

    sa.sa_handler = sig_term;
    if (sigaction(SIGTERM, &sa, NULL) < 0)
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00264)
                     "sigaction(SIGTERM)");
#ifdef SIGINT
    if (sigaction(SIGINT, &sa, NULL) < 0)
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00266)
                     "sigaction(SIGINT)");
#endif
#ifdef AP_SIG_GRACEFUL_STOP
    if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00265)
                     "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
#endif

    /* Don't catch restart signals in ONE_PROCESS mode :) */
    if (!one_process) {
        sa.sa_handler = sig_restart;
        if (sigaction(SIGHUP, &sa, NULL) < 0)
            ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00270)
                         "sigaction(SIGHUP)");
        if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
            ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00271)
                         "sigaction(" AP_SIG_GRACEFUL_STRING ")");
    }

#else  /* NO_USE_SIGACTION */

#ifdef SIGPIPE
    apr_signal(SIGPIPE, SIG_IGN);
#endif /* SIGPIPE */
#ifdef SIGXCPU
    apr_signal(SIGXCPU, SIG_DFL);
#endif /* SIGXCPU */
#ifdef SIGXFSZ
    apr_signal(SIGXFSZ, SIG_IGN);
#endif /* SIGXFSZ */

    apr_signal(SIGTERM, sig_term);
#ifdef AP_SIG_GRACEFUL_STOP
    apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
#endif /* AP_SIG_GRACEFUL_STOP */

    if (!one_process) {
        /* Don't restart in ONE_PROCESS mode :) */
#ifdef SIGHUP
        apr_signal(SIGHUP, sig_restart);
#endif /* SIGHUP */
#ifdef AP_SIG_GRACEFUL
        apr_signal(AP_SIG_GRACEFUL, sig_restart);
#endif /* AP_SIG_GRACEFUL */
    }

#endif /* NO_USE_SIGACTION */

    apr_pool_cleanup_register(pconf, NULL, unset_signals,
                              apr_pool_cleanup_null);
}


#ifdef _OSD_POSIX

#include "apr_lib.h"
+25 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@

#include "httpd.h"
#include "http_config.h"
#include "scoreboard.h"
#include "ap_listen.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@@ -109,6 +110,30 @@ AP_DECLARE(apr_status_t) ap_unixd_accept(void **accepted, ap_listen_rec *lr, apr
#define ap_os_killpg(x, y)      (kill (-(x), (y)))
#endif /* HAVE_KILLPG */

typedef struct {
    void            *baton;  /* MPM's */

    /* volatile because they're updated from signals' handlers */
    int volatile    mpm_state;
    int volatile    shutdown_pending;
    int volatile    restart_pending;
    int volatile    is_ungraceful;

    ap_generation_t my_generation;
    int             module_loads;
    int             was_graceful;

    /*
     * Current number of listeners buckets and maximum reached across
     * restarts (to size retained data according to dynamic num_buckets,
     * eg. idle_spawn_rate).
     */
    int num_buckets, max_buckets;
} ap_unixd_mpm_retained_data;

AP_DECLARE(ap_unixd_mpm_retained_data *) ap_unixd_mpm_get_retained_data(void);
AP_DECLARE(void) ap_unixd_mpm_set_signals(apr_pool_t *pconf, int once_process);

#ifdef __cplusplus
}
#endif
+69 −211

File changed.

Preview size limit exceeded, changes collapsed.

Loading