From: Willy Tarreau Date: Thu, 19 Jan 2023 17:43:48 +0000 (+0100) Subject: MINOR: threads: add a thread_harmless_end() version that doesn't wait X-Git-Tag: v2.8-dev2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7e70bfc8c;p=thirdparty%2Fhaproxy.git MINOR: threads: add a thread_harmless_end() version that doesn't wait thread_harmless_end() needs to wait for rdv_requests to disappear so that we're certain to respect a harmless promise that possibly allowed another thread to proceed under isolation. But this doesn't work in a signal handler because a thread could be interrupted by the debug handler while already waiting for isolation and with rdv_request>0. As such this function could cause a deadlock in such a signal handler. Let's implement a specific variant for this, thread_harmless_end_sig(), that just resets the thread's bit and doesn't wait. It must of course not be used past a check point that would allow the isolation requester to return and see the thread as temporarily harmless then turning back on its promise. This will be needed to fix a race in the debug handler. --- diff --git a/include/haproxy/thread.h b/include/haproxy/thread.h index 2c7856bc27..d6e7bc92ae 100644 --- a/include/haproxy/thread.h +++ b/include/haproxy/thread.h @@ -272,6 +272,18 @@ static inline void thread_harmless_end() } } +/* Ends the harmless period started by thread_harmless_now(), but without + * waiting for isolated requests. This is meant to be used from signal handlers + * which might be called recursively while a thread already requested an + * isolation that must be ignored. It must not be used past a checkpoint where + * another thread could return and see the current thread as harmless before + * this call (or this could validate an isolation request by accident). + */ +static inline void thread_harmless_end_sig() +{ + HA_ATOMIC_AND(&tg_ctx->threads_harmless, ~ti->ltid_bit); +} + /* an isolated thread has its ID in isolated_thread */ static inline unsigned long thread_isolated() {