Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.1

*) mpm_event, mpm_worker, mpm_winnt, mpm_prefork: Added optional functions
to account for connections managed outside the MPM accept loop (e.g., UDP).
[Tarek Ibrahim <tareki@pulsarxtech.com> <t1br4h1m@gmail.com>]

* mod_ssl: Add support for OpenSSL provider based certificate
stores. [Graham Leggett]

Expand Down
2 changes: 1 addition & 1 deletion docs/log-message-tags/next-number
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10622
10623
6 changes: 5 additions & 1 deletion include/ap_mmn.h
Original file line number Diff line number Diff line change
Expand Up @@ -737,14 +737,18 @@
* 20211221.29 (2.5.1-dev) Add ap_set_time_process_request() to scoreboard.h
* 20211221.30 (2.5.1-dev) Add ap_stat_check() to httpd.h
* 20211221.31 (2.5.1-dev) Add ap_*_timingsafe() to httpd.h
* 20211221.32 (2.5.1-dev) Add the optional functions ap_mpm_note_extra_
* connection_added() and ap_mpm_note_extra_
* connection_removed(), and ap_mpm_wait_for_extra_
* connections(), to mpm_common.h
*/

#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */

#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20211221
#endif
#define MODULE_MAGIC_NUMBER_MINOR 31 /* 0...n */
#define MODULE_MAGIC_NUMBER_MINOR 32 /* 0...n */

/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Expand Down
29 changes: 29 additions & 0 deletions include/mpm_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "ap_config.h"
#include "ap_mpm.h"
#include "scoreboard.h"
#include "apr_optional.h"

#if APR_HAVE_NETINET_TCP_H
#include <netinet/tcp.h> /* for TCP_NODELAY */
Expand Down Expand Up @@ -560,6 +561,34 @@ AP_DECLARE_HOOK(void, child_stopped,
*/
void mpm_common_pre_config(apr_pool_t *pconf);

/**
* Report a connection which the MPM did not accept itself, so that a child
* stopping gracefully waits for it like for its own connections. Call
* ap_mpm_note_extra_connection_added() when such a connection starts and
* ap_mpm_note_extra_connection_removed() when it ends.
*/
APR_DECLARE_OPTIONAL_FN(void, ap_mpm_note_extra_connection_added, (void));
APR_DECLARE_OPTIONAL_FN(void, ap_mpm_note_extra_connection_removed, (void));

/**
* Make the above optional functions available to modules. To be called from
* the pre-config hook of an MPM which waits for noted connections.
*
* @note An MPM which does not wait for them never calls this, leaving both
* functions unavailable.
*/
AP_DECLARE(void) ap_mpm_register_extra_connection_fns(void);

/**
* Wait for the connections noted by modules to be gone, for at most
* max(Timeout, GracefulShutdownTimeout). To be called by an MPM child
* that is about to exit gracefully.
*
* @note If tracked connections remain when the timeout expires, a warning is
* logged and the child exits, potentially terminating those connections.
*/
AP_DECLARE(void) ap_mpm_wait_for_extra_connections(void);

#ifdef __cplusplus
}
#endif
Expand Down
26 changes: 25 additions & 1 deletion server/mpm/event/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,10 @@ static apr_status_t event_request_cleanup(void *dummy)
event_conn_state_t *cs = ap_get_module_config(c->conn_config,
&mpm_event_module);

if (!cs) {
return APR_SUCCESS;
}

cs->r = NULL;
return APR_SUCCESS;
}
Expand All @@ -982,6 +986,10 @@ static void event_pre_read_request(request_rec *r, conn_rec *c)
event_conn_state_t *cs = ap_get_module_config(c->conn_config,
&mpm_event_module);

if (!cs) {
return;
}

cs->r = r;
cs->sc = ap_get_module_config(ap_server_conf->module_config,
&mpm_event_module);
Expand All @@ -999,6 +1007,10 @@ static int event_post_read_request(request_rec *r)
event_conn_state_t *cs = ap_get_module_config(c->conn_config,
&mpm_event_module);

if (!cs) {
return DECLINED;
}

/* To preserve legacy behaviour (consistent with other MPMs), use
* the keepalive timeout from the base server (first on this IP:port)
* when none is explicitly configured on this server.
Expand Down Expand Up @@ -3139,6 +3151,10 @@ static void child_main(int child_num_arg, int child_bucket)
rv == AP_MPM_PODX_GRACEFUL ? "graceful" : "ungraceful");
}

if (terminate_mode == ST_GRACEFUL) {
ap_mpm_wait_for_extra_connections();
}

free(threads);

clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
Expand Down Expand Up @@ -3876,6 +3892,10 @@ static void setup_slave_conn(conn_rec *c, void *csd)
event_conn_state_t *cs;

mcs = ap_get_module_config(c->master->conn_config, &mpm_event_module);
if (!mcs) {
/* Master connection is not managed by this MPM; nothing to inherit. */
return;
}

cs = apr_pcalloc(c->pool, sizeof(*cs));
cs->c = c;
Expand Down Expand Up @@ -3914,7 +3934,9 @@ static int event_protocol_switch(conn_rec *c, request_rec *r, server_rec *s,
event_conn_state_t *cs;

cs = ap_get_module_config(c->conn_config, &mpm_event_module);
cs->sc = ap_get_module_config(s->module_config, &mpm_event_module);
if (cs) {
cs->sc = ap_get_module_config(s->module_config, &mpm_event_module);
}
}
return DECLINED;
}
Expand Down Expand Up @@ -3954,6 +3976,8 @@ static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
const char *userdata_key = "mpm_event_module";
int test_atomics = 0;

ap_mpm_register_extra_connection_fns();

debug = ap_exists_config_define("DEBUG");

if (debug) {
Expand Down
5 changes: 5 additions & 0 deletions server/mpm/prefork/prefork.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ static void clean_child_exit_ex(int code, int from_signal)
if (pchild) {
if (!code && !from_signal) {
ap_run_child_stopping(pchild, !retained->mpm->is_ungraceful);
if (!retained->mpm->is_ungraceful) {
ap_mpm_wait_for_extra_connections();
}
ap_run_child_stopped(pchild, !retained->mpm->is_ungraceful);
}
apr_pool_destroy(pchild);
Expand Down Expand Up @@ -1325,6 +1328,8 @@ static int prefork_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp
apr_status_t rv;
const char *userdata_key = "mpm_prefork_module";

ap_mpm_register_extra_connection_fns();

debug = ap_exists_config_define("DEBUG");

if (debug) {
Expand Down
4 changes: 4 additions & 0 deletions server/mpm/winnt/child.c
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,10 @@ void child_main(apr_pool_t *pconf, DWORD parent_pid)
ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, APLOGNO(00364)
"Child: All worker threads have exited.");

if (graceful_shutdown) {
ap_mpm_wait_for_extra_connections();
}

ap_run_child_stopped(pchild, graceful_shutdown);

apr_thread_mutex_destroy(child_lock);
Expand Down
2 changes: 2 additions & 0 deletions server/mpm/winnt/mpm_winnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,8 @@ static int winnt_pre_config(apr_pool_t *pconf_, apr_pool_t *plog, apr_pool_t *pt
* -k runservice [WinNT errors logged from rewrite_args]
*/

ap_mpm_register_extra_connection_fns();

/* Initialize shared static objects.
* TODO: Put config related statics into an sconf structure.
*/
Expand Down
6 changes: 6 additions & 0 deletions server/mpm/worker/worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,10 @@ static void child_main(int child_num_arg, int child_bucket)
rv == AP_MPM_PODX_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
}

if (terminate_mode == ST_GRACEFUL) {
ap_mpm_wait_for_extra_connections();
}

free(threads);

clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
Expand Down Expand Up @@ -2103,6 +2107,8 @@ static int worker_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_status_t rv;
const char *userdata_key = "mpm_worker_module";

ap_mpm_register_extra_connection_fns();

debug = ap_exists_config_define("DEBUG");

if (debug) {
Expand Down
47 changes: 47 additions & 0 deletions server/mpm_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "apr_getopt.h"
#include "apr_optional.h"
#include "apr_allocator.h"
#include "apr_atomic.h"

#include "httpd.h"
#include "http_config.h"
Expand Down Expand Up @@ -185,6 +186,52 @@ AP_DECLARE_DATA apr_size_t ap_thread_stacksize;
#define ALLOCATOR_MAX_FREE_DEFAULT (2048*1024)
AP_DECLARE_DATA apr_uint32_t ap_max_mem_free = ALLOCATOR_MAX_FREE_DEFAULT;

static apr_uint32_t extra_connection_count = 0; /* Number of open connections that the MPM does not own */

static void ap_mpm_note_extra_connection_added(void)
{
apr_atomic_inc32(&extra_connection_count);
}

static void ap_mpm_note_extra_connection_removed(void)
{
apr_atomic_dec32(&extra_connection_count);
}

AP_DECLARE(void) ap_mpm_register_extra_connection_fns(void)
{
APR_REGISTER_OPTIONAL_FN(ap_mpm_note_extra_connection_added);
APR_REGISTER_OPTIONAL_FN(ap_mpm_note_extra_connection_removed);
}

AP_DECLARE(void) ap_mpm_wait_for_extra_connections(void)
{
apr_uint32_t count = apr_atomic_read32(&extra_connection_count);
apr_time_t graceful, timeout, deadline;

if (count == 0) {
return;
}

graceful = apr_time_from_sec(ap_graceful_shutdown_timeout);
timeout = (graceful > ap_server_conf->timeout) ? graceful : ap_server_conf->timeout;
deadline = apr_time_now() + timeout;

do {
apr_sleep(apr_time_from_msec(100));
count = apr_atomic_read32(&extra_connection_count);
} while (count > 0 && apr_time_now() < deadline);

if (count > 0) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
APLOGNO(10622)
"Child: %u connection(s) noted by modules did not "
"finish within %" APR_TIME_T_FMT " seconds, "
"exiting anyway",
count, apr_time_sec(timeout));
}
}

/* Set defaults for config directives implemented here. This is
* called from core's pre-config hook, so MPMs which need to override
* one of these should run their pre-config hook after that of core.
Expand Down