From: Graham Leggett Date: Wed, 8 Jul 2020 12:07:38 +0000 (+0000) Subject: *) mod_watchdog: Switch to simpler logic to avoid the thread cleanup running X-Git-Tag: 2.4.44~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c3638c9d1a520cba773680e55a6cf3b3f402d53b;p=thirdparty%2Fapache%2Fhttpd.git *) mod_watchdog: Switch to simpler logic to avoid the thread cleanup running before the thread has started, avoiding mutex operations with undefined behaviour. [Christophe Jaillet] git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1879645 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 31ad6741715..b6d0f476459 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.4.44 + *) mod_watchdog: Switch to simpler logic to avoid the thread cleanup running + before the thread has started, avoiding mutex operations with undefined + behaviour. [Christophe Jaillet] + *) mod_http2: The module now handles master/secondary connections and has marked methods according to use. [Stefan Eissing] diff --git a/STATUS b/STATUS index e558da08eab..566a0189e12 100644 --- a/STATUS +++ b/STATUS @@ -135,11 +135,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - *) mod_watchdog: Switch to simpler logic to avoid the thread cleanup running - before the thread has started, avoiding mutex operations with undefined behaviour - trunk patch: http://svn.apache.org/r1876511 - 2.4.x patch: svn merge -c 1876511 ^/httpd/httpd/trunk . - +1: jailletc36 (by inspection), jim, minfrin PATCHES PROPOSED TO BACKPORT FROM TRUNK: diff --git a/modules/core/mod_watchdog.c b/modules/core/mod_watchdog.c index 51dea91c69e..bc05e852115 100644 --- a/modules/core/mod_watchdog.c +++ b/modules/core/mod_watchdog.c @@ -24,6 +24,8 @@ #include "http_core.h" #include "util_mutex.h" +#include "apr_atomic.h" + #define AP_WATCHDOG_PGROUP "watchdog" #define AP_WATCHDOG_PVERSION "parent" #define AP_WATCHDOG_CVERSION "child" @@ -43,7 +45,7 @@ struct watchdog_list_t struct ap_watchdog_t { - apr_thread_mutex_t *startup; + apr_uint32_t thread_started; /* set to 1 once thread running */ apr_proc_mutex_t *mutex; const char *name; watchdog_list_t *callbacks; @@ -74,6 +76,10 @@ static apr_status_t wd_worker_cleanup(void *data) apr_status_t rv; ap_watchdog_t *w = (ap_watchdog_t *)data; + /* Do nothing if the thread wasn't started. */ + if (apr_atomic_read32(&w->thread_started) != 1) + return APR_SUCCESS; + if (w->is_running) { watchdog_list_t *wl = w->callbacks; while (wl) { @@ -110,7 +116,8 @@ static void* APR_THREAD_FUNC wd_worker(apr_thread_t *thread, void *data) w->pool = apr_thread_pool_get(thread); w->is_running = 1; - apr_thread_mutex_unlock(w->startup); + apr_atomic_set32(&w->thread_started, 1); /* thread started */ + if (w->mutex) { while (w->is_running) { if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) { @@ -264,10 +271,7 @@ static apr_status_t wd_startup(ap_watchdog_t *w, apr_pool_t *p) { apr_status_t rc; - /* Create thread startup mutex */ - rc = apr_thread_mutex_create(&w->startup, APR_THREAD_MUTEX_UNNESTED, p); - if (rc != APR_SUCCESS) - return rc; + apr_atomic_set32(&w->thread_started, 0); if (w->singleton) { /* Initialize singleton mutex in child */ @@ -277,22 +281,12 @@ static apr_status_t wd_startup(ap_watchdog_t *w, apr_pool_t *p) return rc; } - /* This mutex fixes problems with a fast start/fast end, where the pool - * cleanup was being invoked before the thread completely spawned. - */ - apr_thread_mutex_lock(w->startup); - apr_pool_pre_cleanup_register(p, w, wd_worker_cleanup); - /* Start the newly created watchdog */ rc = apr_thread_create(&w->thread, NULL, wd_worker, w, p); - if (rc) { - apr_pool_cleanup_kill(p, w, wd_worker_cleanup); + if (rc == APR_SUCCESS) { + apr_pool_pre_cleanup_register(p, w, wd_worker_cleanup); } - apr_thread_mutex_lock(w->startup); - apr_thread_mutex_unlock(w->startup); - apr_thread_mutex_destroy(w->startup); - return rc; }