[Libreoffice-commits] core.git: sal/osl

Stephan Bergmann sbergman at redhat.com
Wed Feb 1 11:37:52 UTC 2017


 sal/osl/unx/signal.cxx |  125 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 77 insertions(+), 48 deletions(-)

New commits:
commit 5997121a51e240c762b4d002d7d16b94ac13d4a1
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Wed Feb 1 12:30:23 2017 +0100

    Support signal handlers registered with SA_SIGINFO
    
    ...as is the case for external/breakpad's
    google_breakpad::ExceptionHandler::SignalHandler (though that one appears to be
    careful to check that its additional arguments are not garbage, cf. the
    "Sometime, Breakpad runs inside a process where some other buggy code..."
    comment in
    workdir/UnpackedTarball/breakpad/src/client/linux/handler/exception_handler.cc).
    
    Seen when JunitTest_framework_complex run under ASan/UBSan happened to trigger
    an assert,
    
    > soffice.bin: vcl/source/app/dbggui.cxx:47: void ImplDbgTestSolarMutex(): Assertion `ImplGetSVData()->mpDefInst->CheckYieldMutex() && "SolarMutex not locked"' failed.
    > sal/osl/unx/signal.cxx:349:13: runtime error: call to function google_breakpad::ExceptionHandler::SignalHandler(int, siginfo_t*, void*) through pointer to incorrect function type 'void (*)(int)'
    > (instdir/program/libsofficeapp.so+0xb7eab0): note: google_breakpad::ExceptionHandler::SignalHandler(int, siginfo_t*, void*) defined here
    >     #0 0x7f6cefc21693 in (anonymous namespace)::callSystemHandler(int) sal/osl/unx/signal.cxx:349:13
    >     #1 0x7f6cefc1f3e1 in (anonymous namespace)::signalHandlerFunction(int) sal/osl/unx/signal.cxx:422:9
    >     #2 0x7f6cedbc95bf  (/lib64/libpthread.so.0+0x115bf)
    >     #3 0x7f6ced20491e in __libc_signal_restore_set /usr/src/debug/glibc-2.24-33-ge9e69e4/signal/../sysdeps/unix/sysv/linux/nptl-signals.h:79
    >     #4 0x7f6ced20491e in __GI_raise /usr/src/debug/glibc-2.24-33-ge9e69e4/signal/../sysdeps/unix/sysv/linux/raise.c:55
    >     #5 0x7f6ced206519 in __GI_abort /usr/src/debug/glibc-2.24-33-ge9e69e4/stdlib/abort.c:89
    >     #6 0x7f6ced1fcda6 in __assert_fail_base /usr/src/debug/glibc-2.24-33-ge9e69e4/assert/assert.c:92
    >     #7 0x7f6ced1fce51 in __GI___assert_fail /usr/src/debug/glibc-2.24-33-ge9e69e4/assert/assert.c:101
    >     #8 0x7f6cb60cdad5 in ImplDbgTestSolarMutex() vcl/source/app/dbggui.cxx:47:5
    >     #9 0x7f6cbd337fb9 in DbgTestSolarMutex() tools/source/debug/debug.cxx:74:9
    >     #10 0x7f6cb3c98abf in vcl::Window::ReleaseGraphics(bool) vcl/source/window/window.cxx:900:5
    ...
    
    Change-Id: I2625541e0b9e50f9723e61e0cbff0e6c77d0fb9f

diff --git a/sal/osl/unx/signal.cxx b/sal/osl/unx/signal.cxx
index b127272..2cf6d7e 100644
--- a/sal/osl/unx/signal.cxx
+++ b/sal/osl/unx/signal.cxx
@@ -73,63 +73,66 @@
 
 namespace
 {
+extern "C" using Handler1 = void (*)(int);
+extern "C" using Handler2 = void (*)(int, siginfo_t *, void *);
 struct SignalAction
 {
     int Signal;
     int Action;
-    void (*Handler)(int);
+    Handler1 Handler;
+    bool siginfo; // Handler's type is Handler2
 } Signals[] =
 {
-    { SIGHUP,    ACT_HIDE, SIG_DFL },    /* hangup */
-    { SIGINT,    ACT_EXIT,   SIG_DFL },    /* interrupt (rubout) */
-    { SIGQUIT,   ACT_EXIT,  SIG_DFL },    /* quit (ASCII FS) */
-    { SIGILL,    ACT_SYSTEM,  SIG_DFL },    /* illegal instruction (not reset when caught) */
+    { SIGHUP,    ACT_HIDE, SIG_DFL, false }, /* hangup */
+    { SIGINT,    ACT_EXIT,   SIG_DFL, false }, /* interrupt (rubout) */
+    { SIGQUIT,   ACT_EXIT,  SIG_DFL, false }, /* quit (ASCII FS) */
+    { SIGILL,    ACT_SYSTEM,  SIG_DFL, false }, /* illegal instruction (not reset when caught) */
 /* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/
-    { SIGTRAP,   ACT_ABORT,  SIG_DFL },    /* trace trap (not reset when caught) */
+    { SIGTRAP,   ACT_ABORT,  SIG_DFL, false }, /* trace trap (not reset when caught) */
 #if ( SIGIOT != SIGABRT )
-    { SIGIOT,    ACT_ABORT,  SIG_DFL },    /* IOT instruction */
+    { SIGIOT,    ACT_ABORT,  SIG_DFL, false }, /* IOT instruction */
 #endif
-    { SIGABRT,   ACT_ABORT,  SIG_DFL },    /* used by abort, replace SIGIOT in the future */
+    { SIGABRT,   ACT_ABORT,  SIG_DFL, false }, /* used by abort, replace SIGIOT in the future */
 #ifdef SIGEMT
-    { SIGEMT,    ACT_SYSTEM,  SIG_DFL },    /* EMT instruction */
+    { SIGEMT,    ACT_SYSTEM,  SIG_DFL, false }, /* EMT instruction */
 /* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/
 /* SIGEMT may also be used by the profiler - so it is probably not a good
 plan to have the new handler use this signal*/
 #endif
-    { SIGFPE,    ACT_ABORT,  SIG_DFL },    /* floating point exception */
-    { SIGKILL,   ACT_SYSTEM, SIG_DFL },    /* kill (cannot be caught or ignored) */
-    { SIGBUS,    ACT_ABORT,  SIG_DFL },    /* bus error */
-    { SIGSEGV,   ACT_ABORT,  SIG_DFL },    /* segmentation violation */
+    { SIGFPE,    ACT_ABORT,  SIG_DFL, false }, /* floating point exception */
+    { SIGKILL,   ACT_SYSTEM, SIG_DFL, false }, /* kill (cannot be caught or ignored) */
+    { SIGBUS,    ACT_ABORT,  SIG_DFL, false }, /* bus error */
+    { SIGSEGV,   ACT_ABORT,  SIG_DFL, false }, /* segmentation violation */
 #ifdef SIGSYS
-    { SIGSYS,    ACT_ABORT,  SIG_DFL },    /* bad argument to system call */
+    { SIGSYS,    ACT_ABORT,  SIG_DFL, false }, /* bad argument to system call */
 #endif
-    { SIGPIPE,   ACT_HIDE,   SIG_DFL },    /* write on a pipe with no one to read it */
-    { SIGALRM,   ACT_EXIT,   SIG_DFL },    /* alarm clock */
-    { SIGTERM,   ACT_EXIT,   SIG_DFL },    /* software termination signal from kill */
-    { SIGUSR1,   ACT_SYSTEM, SIG_DFL },    /* user defined signal 1 */
-    { SIGUSR2,   ACT_SYSTEM, SIG_DFL },    /* user defined signal 2 */
-    { SIGCHLD,   ACT_SYSTEM, SIG_DFL },    /* child status change */
+    { SIGPIPE,   ACT_HIDE,   SIG_DFL, false }, /* write on a pipe with no one to read it */
+    { SIGALRM,   ACT_EXIT,   SIG_DFL, false }, /* alarm clock */
+    { SIGTERM,   ACT_EXIT,   SIG_DFL, false }, /* software termination signal from kill */
+    { SIGUSR1,   ACT_SYSTEM, SIG_DFL, false }, /* user defined signal 1 */
+    { SIGUSR2,   ACT_SYSTEM, SIG_DFL, false }, /* user defined signal 2 */
+    { SIGCHLD,   ACT_SYSTEM, SIG_DFL, false }, /* child status change */
 #ifdef SIGPWR
-    { SIGPWR,    ACT_IGNORE, SIG_DFL },    /* power-fail restart */
+    { SIGPWR,    ACT_IGNORE, SIG_DFL, false }, /* power-fail restart */
 #endif
-    { SIGWINCH,  ACT_IGNORE, SIG_DFL },    /* window size change */
-    { SIGURG,    ACT_EXIT,   SIG_DFL },    /* urgent socket condition */
+    { SIGWINCH,  ACT_IGNORE, SIG_DFL, false }, /* window size change */
+    { SIGURG,    ACT_EXIT,   SIG_DFL, false }, /* urgent socket condition */
 #ifdef SIGPOLL
-    { SIGPOLL,   ACT_EXIT,   SIG_DFL },    /* pollable event occurred */
+    { SIGPOLL,   ACT_EXIT,   SIG_DFL, false }, /* pollable event occurred */
 #endif
-    { SIGSTOP,   ACT_SYSTEM, SIG_DFL },    /* stop (cannot be caught or ignored) */
-    { SIGTSTP,   ACT_SYSTEM, SIG_DFL },    /* user stop requested from tty */
-    { SIGCONT,   ACT_SYSTEM, SIG_DFL },    /* stopped process has been continued */
-    { SIGTTIN,   ACT_SYSTEM, SIG_DFL },    /* background tty read attempted */
-    { SIGTTOU,   ACT_SYSTEM, SIG_DFL },    /* background tty write attempted */
-    { SIGVTALRM, ACT_EXIT,   SIG_DFL },    /* virtual timer expired */
-    { SIGPROF,   ACT_SYSTEM,   SIG_DFL },    /* profiling timer expired */
+    { SIGSTOP,   ACT_SYSTEM, SIG_DFL, false }, /* stop (cannot be caught or ignored) */
+    { SIGTSTP,   ACT_SYSTEM, SIG_DFL, false }, /* user stop requested from tty */
+    { SIGCONT,   ACT_SYSTEM, SIG_DFL, false }, /* stopped process has been continued */
+    { SIGTTIN,   ACT_SYSTEM, SIG_DFL, false }, /* background tty read attempted */
+    { SIGTTOU,   ACT_SYSTEM, SIG_DFL, false }, /* background tty write attempted */
+    { SIGVTALRM, ACT_EXIT,   SIG_DFL, false }, /* virtual timer expired */
+    { SIGPROF,   ACT_SYSTEM,   SIG_DFL, false }, /* profiling timer expired */
 /*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do
 not get taken by the new handler - the new handler does not pass on context
 information which causes 'collect' to crash. This is a way of avoiding
 what looks like a bug in the new handler*/
-    { SIGXCPU,   ACT_ABORT,  SIG_DFL },    /* exceeded cpu limit */
-    { SIGXFSZ,   ACT_ABORT,  SIG_DFL }     /* exceeded file size limit */
+    { SIGXCPU,   ACT_ABORT,  SIG_DFL, false }, /* exceeded cpu limit */
+    { SIGXFSZ,   ACT_ABORT,  SIG_DFL, false }  /* exceeded file size limit */
 };
 const int NoSignals = sizeof(Signals) / sizeof(struct SignalAction);
 
@@ -137,7 +140,7 @@ bool bSetSEGVHandler = false;
 bool bSetWINCHHandler = false;
 bool bSetILLHandler = false;
 
-void signalHandlerFunction(int);
+void signalHandlerFunction(int, siginfo_t *, void *);
 
 void getExecutableName_Impl (rtl_String ** ppstrProgName)
 {
@@ -202,8 +205,8 @@ bool onInitSignal()
 #endif
 
     struct sigaction act;
-    act.sa_handler = signalHandlerFunction;
-    act.sa_flags   = SA_RESTART;
+    act.sa_sigaction = signalHandlerFunction;
+    act.sa_flags = SA_RESTART | SA_SIGINFO;
 
     sigfillset(&(act.sa_mask));
 
@@ -231,18 +234,34 @@ bool onInitSignal()
                     sigemptyset(&ign.sa_mask);
 
                     struct sigaction oact;
-                    if (sigaction(rSignal.Signal, &ign, &oact) == 0)
-                        rSignal.Handler = oact.sa_handler;
-                    else
+                    if (sigaction(rSignal.Signal, &ign, &oact) == 0) {
+                        rSignal.siginfo = (oact.sa_flags & SA_SIGINFO) != 0;
+                        if (rSignal.siginfo) {
+                            rSignal.Handler = reinterpret_cast<Handler1>(
+                                oact.sa_sigaction);
+                        } else {
+                            rSignal.Handler = oact.sa_handler;
+                        }
+                    } else {
                         rSignal.Handler = SIG_DFL;
+                        rSignal.siginfo = false;
+                    }
                 }
                 else
                 {
                     struct sigaction oact;
-                    if (sigaction(rSignal.Signal, &act, &oact) == 0)
-                        rSignal.Handler = oact.sa_handler;
-                    else
+                    if (sigaction(rSignal.Signal, &act, &oact) == 0) {
+                        rSignal.siginfo = (oact.sa_flags & SA_SIGINFO) != 0;
+                        if (rSignal.siginfo) {
+                            rSignal.Handler = reinterpret_cast<Handler1>(
+                                oact.sa_sigaction);
+                        } else {
+                            rSignal.Handler = oact.sa_handler;
+                        }
+                    } else {
                         rSignal.Handler = SIG_DFL;
+                        rSignal.siginfo = false;
+                    }
                 }
             }
         }
@@ -266,14 +285,20 @@ bool onDeInitSignal()
 {
     struct sigaction act;
 
-    act.sa_flags   = 0;
     sigemptyset(&(act.sa_mask));
 
     /* Initialize the rest of the signals */
     for (int i = NoSignals - 1; i >= 0; i--)
         if (Signals[i].Action != ACT_SYSTEM)
         {
-            act.sa_handler = Signals[i].Handler;
+            if (Signals[i].siginfo) {
+                act.sa_sigaction = reinterpret_cast<Handler2>(
+                    Signals[i].Handler);
+                act.sa_flags = SA_SIGINFO;
+            } else {
+                act.sa_handler = Signals[i].Handler;
+                act.sa_flags = 0;
+            }
 
             sigaction(Signals[i].Signal, &act, nullptr);
         }
@@ -305,7 +330,7 @@ void printStack(int sig)
 #endif
 }
 
-void callSystemHandler(int signal)
+void callSystemHandler(int signal, siginfo_t * info, void * context)
 {
     int i;
 
@@ -345,8 +370,12 @@ void callSystemHandler(int signal)
                     OSL_ASSERT(false);
             }
         }
-        else
+        else if (Signals[i].siginfo) {
+            (*reinterpret_cast<Handler2>(Signals[i].Handler))(
+                signal, info, context);
+        } else {
             (*Signals[i].Handler)(signal);
+        }
     }
 }
 
@@ -370,7 +399,7 @@ void DUMPCURRENTALLOCS()
 }
 #endif
 
-void signalHandlerFunction(int signal)
+void signalHandlerFunction(int signal, siginfo_t * info, void * context)
 {
     oslSignalInfo Info;
 
@@ -419,7 +448,7 @@ void signalHandlerFunction(int signal)
     switch (callSignalHandler(&Info))
     {
     case osl_Signal_ActCallNextHdl:
-        callSystemHandler(signal);
+        callSystemHandler(signal, info, context);
         break;
 
     case osl_Signal_ActAbortApp:


More information about the Libreoffice-commits mailing list