From 3fe0a999d7a89141c7c03ca797fc7d65e07e9c52 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Mon, 28 Feb 2022 23:40:21 +0100 Subject: Avoid race condition during Unix signal handling Handling a signal in the "Forwarded" handler while simultaneously applying a signal mask reset in the low-level handler would lead to a race condition accessing m_handlers. Change-Id: If7d27b7c3515faef894c585cd73bc461e8444ee5 Reviewed-by: Dominik Holland (cherry picked from commit ed404c4fdb7d1c74dca554dc9ae4d5d0903c9bc2) Reviewed-by: Qt CI Bot --- src/common-lib/unixsignalhandler.cpp | 30 ++++++++++++++++++------------ src/common-lib/unixsignalhandler.h | 1 + 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/common-lib/unixsignalhandler.cpp b/src/common-lib/unixsignalhandler.cpp index d74e5e44..802e0db8 100644 --- a/src/common-lib/unixsignalhandler.cpp +++ b/src/common-lib/unixsignalhandler.cpp @@ -139,8 +139,8 @@ bool UnixSignalHandler::install(Type handlerType, const std::initializer_listm_currentSignal = sig; - for (const auto &h : that->m_handlers) { - if (h.m_signal == sig) { + for (const auto &h : qAsConst(that->m_handlers)) { + if ((h.m_signal == sig) && !h.m_disabled) { if (!h.m_qt) { h.m_handler(sig); } else { @@ -157,10 +157,14 @@ bool UnixSignalHandler::install(Type handlerType, const std::initializer_listm_resetSignalMask) { - // someone called resetToDefault - now's a good time to handle it - that->m_handlers.remove_if([that](const SigHandler &h) { - return that->m_resetSignalMask & am_sigmask(h.m_signal); - }); + // Someone called resetToDefault - now's a good time to handle it. + // We can not remove the entries in the list, because that would (a) allocate and (b) + // step on code that might be iterating over the list in the "Forwarded" handler. + + for (const auto &h : qAsConst(that->m_handlers)) { + if (that->m_resetSignalMask & am_sigmask(h.m_signal)) + h.m_disabled = true; + } that->m_resetSignalMask = 0; } that->m_currentSignal = 0; @@ -186,8 +190,8 @@ bool UnixSignalHandler::install(Type handlerType, const std::initializer_listm_handlers) { - if (h.m_qt && h.m_signal == sig) + for (const auto &h : qAsConst(m_handlers)) { + if (h.m_qt && (h.m_signal == sig) && !h.m_disabled) h.m_handler(sig); } }); @@ -200,8 +204,8 @@ bool UnixSignalHandler::install(Type handlerType, const std::initializer_listm_handlers) { - if (h.m_qt && h.m_signal == sig) + for (const auto &h : qAsConst(m_handlers)) { + if (h.m_qt && (h.m_signal == sig) && !h.m_disabled) h.m_handler(sig); } } @@ -212,12 +216,14 @@ bool UnixSignalHandler::install(Type handlerType, const std::initializer_list m_handler; + mutable QAtomicInteger m_disabled; }; std::list m_handlers; // we're using STL to avoid (accidental) implicit copies -- cgit v1.2.1