common/SigUtil.cpp | 43 ++++++++++++++++++++++++++++++++++++++----- common/SigUtil.hpp | 12 +++++------- kit/Kit.cpp | 5 ++--- 3 files changed, 45 insertions(+), 15 deletions(-)
New commits: commit b74306acd5c833363cf6c116913c134bb02ddac1 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> AuthorDate: Mon Nov 18 09:12:30 2019 -0500 Commit: Ashod Nakashian <ashnak...@gmail.com> CommitDate: Tue Nov 19 16:12:29 2019 +0100 wsd: replace mutex in signal handler There are a few things acceptable/safe in a signal handler, and taking locks is not one of them. This replaces the logic with a simple counter that serves the purpose just as well. If we get a double signal, we log and ignore. Change-Id: If589c18492468c120d00c213805467bcbba05d27 Reviewed-on: https://gerrit.libreoffice.org/83150 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/common/SigUtil.cpp b/common/SigUtil.cpp index be626ff6b..e5dabcb6f 100644 --- a/common/SigUtil.cpp +++ b/common/SigUtil.cpp @@ -83,13 +83,38 @@ namespace SigUtil } #if !MOBILEAPP -std::mutex SigHandlerTrap; - namespace SigUtil { - std::mutex& getSigHandlerTrap() + /// This traps the signal-handler so we don't _Exit + /// while dumping stack trace. It's re-entrant. + /// Used to safely increment and decrement the signal-handler trap. + class SigHandlerTrap + { + static std::atomic<int> SigHandling; + public: + SigHandlerTrap() { ++SigHandlerTrap::SigHandling; } + ~SigHandlerTrap() { --SigHandlerTrap::SigHandling; } + + /// Check that we have exclusive access to the trap. + /// Otherwise, there is another signal in progress. + bool isExclusive() const + { + // Return true if we are alone. + return SigHandlerTrap::SigHandling == 1; + } + + /// Wait for the trap to clear. + static void wait() + { + while (SigHandlerTrap::SigHandling) + sleep(1); + } + }; + std::atomic<int> SigHandlerTrap::SigHandling; + + void waitSigHandlerTrap() { - return SigHandlerTrap; + SigHandlerTrap::wait(); } const char *signalName(const int signo) @@ -211,7 +236,15 @@ namespace SigUtil static void handleFatalSignal(const int signal) { - std::unique_lock<std::mutex> lock(SigHandlerTrap); + SigHandlerTrap guard; + if (!guard.isExclusive()) + { + Log::signalLogPrefix(); + Log::signalLog(" Fatal double signal received: "); + Log::signalLog(signalName(signal)); + Log::signalLog("\n Already handling a signal; will ignore this."); + return; + } Log::signalLogPrefix(); Log::signalLog(" Fatal signal received: "); diff --git a/common/SigUtil.hpp b/common/SigUtil.hpp index caf8d531d..95371f3a1 100644 --- a/common/SigUtil.hpp +++ b/common/SigUtil.hpp @@ -38,14 +38,12 @@ namespace SigUtil bool getDumpGlobalState(); /// Reset the flag to dump internal state. void resetDumpGlobalState(); -} #if !MOBILEAPP -namespace SigUtil -{ - /// Mutex to trap signal handler, if any, + + /// Wait for the signal handler, if any, /// and prevent _Exit while collecting backtrace. - std::mutex& getSigHandlerTrap(); + void waitSigHandlerTrap(); /// Returns the name of the signal. const char* signalName(int signo); @@ -78,10 +76,10 @@ namespace SigUtil /// Dump a signal-safe back-trace void dumpBacktrace(); -} // end namespace SigUtil - #endif // !MOBILEAPP +} // end namespace SigUtil + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/kit/Kit.cpp b/kit/Kit.cpp index d04277bf8..101a40445 100644 --- a/kit/Kit.cpp +++ b/kit/Kit.cpp @@ -2641,11 +2641,10 @@ void lokit_main( #if !MOBILEAPP - // Trap the signal handler, if invoked, - // to prevent exiting. LOG_INF("Process finished."); Log::shutdown(); - std::unique_lock<std::mutex> lock(SigUtil::getSigHandlerTrap()); + // Wait for the signal handler, if invoked, to prevent exiting until done. + SigUtil::waitSigHandlerTrap(); std::_Exit(EX_OK); #endif _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits