]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: threads: add a thread_harmless_end() version that doesn't wait
authorWilly Tarreau <w@1wt.eu>
Thu, 19 Jan 2023 17:43:48 +0000 (18:43 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 19 Jan 2023 18:22:17 +0000 (19:22 +0100)
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.

include/haproxy/thread.h

index 2c7856bc27f39d64485fc9a29fd56ef1c4e74227..d6e7bc92ae357ded1fa1cfbdf6b46250e6270734 100644 (file)
@@ -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()
 {