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

Reply via email to