Fix signal segfaults on Solaris (#3790)
[ghc-hetmet.git] / rts / posix / Signals.c
index 6d5ef43..4bb1255 100644 (file)
@@ -6,18 +6,15 @@
  *
  * ---------------------------------------------------------------------------*/
 
-/* This is non-Posix-compliant.
-   #include "PosixSource.h" 
-*/
+#include "PosixSource.h" 
 #include "Rts.h"
-#include "SchedAPI.h"
+
 #include "Schedule.h"
 #include "RtsSignals.h"
-#include "posix/Signals.h"
+#include "Signals.h"
 #include "RtsUtils.h"
-#include "RtsFlags.h"
 #include "Prelude.h"
-#include "ThrIOManager.h"
+#include "Stable.h"
 
 #ifdef alpha_HOST_ARCH
 # if defined(linux_HOST_OS)
@@ -89,6 +86,7 @@ static int io_manager_pipe = -1;
 
 #define IO_MANAGER_WAKEUP 0xff
 #define IO_MANAGER_DIE    0xfe
+#define IO_MANAGER_SYNC   0xfd
 
 void
 setIOManagerPipe (int fd)
@@ -98,29 +96,51 @@ setIOManagerPipe (int fd)
     io_manager_pipe = fd;
 }
 
-#if defined(THREADED_RTS)
 void
 ioManagerWakeup (void)
 {
+    int r;
     // Wake up the IO Manager thread by sending a byte down its pipe
     if (io_manager_pipe >= 0) {
        StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
-       write(io_manager_pipe, &byte, 1);
+       r = write(io_manager_pipe, &byte, 1);
+        if (r == -1) { sysErrorBelch("ioManagerWakeup: write"); }
     }
 }
 
 void
+ioManagerSync (void)
+{
+    int r;
+    // Wake up the IO Manager thread by sending a byte down its pipe
+    if (io_manager_pipe >= 0) {
+       StgWord8 byte = (StgWord8)IO_MANAGER_SYNC;
+       r = write(io_manager_pipe, &byte, 1);
+        if (r == -1) { sysErrorBelch("ioManagerSync: write"); }
+    }
+}
+
+#if defined(THREADED_RTS)
+void
 ioManagerDie (void)
 {
+    int r;
     // Ask the IO Manager thread to exit
     if (io_manager_pipe >= 0) {
        StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
-       write(io_manager_pipe, &byte, 1);
+       r = write(io_manager_pipe, &byte, 1);
+        if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
         close(io_manager_pipe);
         io_manager_pipe = -1;
     }
 }
 
+Capability *
+ioManagerStartCap (Capability *cap)
+{
+    return rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
+}
+
 void
 ioManagerStart (void)
 {
@@ -128,7 +148,7 @@ ioManagerStart (void)
     Capability *cap;
     if (io_manager_pipe < 0) {
        cap = rts_lock();
-       cap = rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
+       cap = ioManagerStartCap(cap);
        rts_unlock(cap);
     }
 }
@@ -163,7 +183,14 @@ generic_handler(int sig USED_IF_THREADS,
         int r;
 
         buf[0] = sig;
-        memcpy(buf+1, info, sizeof(siginfo_t));
+
+       if (info == NULL) {
+           // info may be NULL on Solaris (see #3790)
+           memset(buf+1, 0, sizeof(siginfo_t));
+       } else {
+           memcpy(buf+1, info, sizeof(siginfo_t));
+       }
+
        r = write(io_manager_pipe, buf, sizeof(siginfo_t)+1);
         if (r == -1 && errno == EAGAIN)
         {