[project @ 2004-11-14 10:47:26 by malcolm]
[haskell-directory.git] / System / Posix / Signals.hsc
index 6be1644..3585ddb 100644 (file)
 --
 -----------------------------------------------------------------------------
 
+#include "ghcconfig.h"
+
 module System.Posix.Signals (
+#ifndef mingw32_TARGET_OS
   -- * The Signal type
   Signal,
 
@@ -38,7 +41,9 @@ module System.Posix.Signals (
   backgroundWrite, sigTTOU,
   userDefinedSignal1, sigUSR1,
   userDefinedSignal2, sigUSR2,
+#ifdef SIGPOLL
   pollableEvent, sigPOLL,
+#endif
   profilingTimerExpired, sigPROF,
   badSystemCall, sigSYS,
   breakpointTrap, sigTRAP,
@@ -52,9 +57,11 @@ module System.Posix.Signals (
   signalProcess,
   signalProcessGroup,
 
+#ifdef __GLASGOW_HASKELL__
   -- * Handling signals
   Handler(..),
   installHandler,
+#endif
 
   -- * Signal sets
   SignalSet,
@@ -68,7 +75,15 @@ module System.Posix.Signals (
   scheduleAlarm,
 
   -- * Waiting for signals
-  getPendingSignals, awaitSignal,
+  getPendingSignals,
+#ifndef cygwin32_TARGET_OS
+  awaitSignal,
+#endif
+
+#ifdef __GLASGOW_HASKELL__
+  -- * The @NOCLDSTOP@ flag
+  setStoppedChildFlag, queryStoppedChildFlag,
+#endif
 
   -- MISSING FUNCTIONALITY:
   -- sigaction(), (inc. the sigaction structure + flags etc.)
@@ -76,16 +91,23 @@ module System.Posix.Signals (
   -- sigaltstack()
   -- sighold, sigignore, sigpause, sigrelse, sigset
   -- siginterrupt
-
+#endif
   ) where
 
+#ifdef __GLASGOW_HASKELL__
 #include "Signals.h"
+#else
+#include "HsBase.h"
+#endif
 
 import Foreign
 import Foreign.C
 import System.IO.Unsafe
 import System.Posix.Types
-import GHC.Posix
+import System.Posix.Internals
+
+#ifndef mingw32_TARGET_OS
+-- WHOLE FILE...
 
 -- -----------------------------------------------------------------------------
 -- Specific signals
@@ -95,34 +117,69 @@ type Signal = CInt
 nullSignal :: Signal
 nullSignal = 0
 
-foreign import ccall "__hsposix_SIGABRT"   sigABRT   :: CInt
-foreign import ccall "__hsposix_SIGALRM"   sigALRM   :: CInt
-foreign import ccall "__hsposix_SIGBUS"    sigBUS    :: CInt
-foreign import ccall "__hsposix_SIGCHLD"   sigCHLD   :: CInt
-foreign import ccall "__hsposix_SIGCONT"   sigCONT   :: CInt
-foreign import ccall "__hsposix_SIGFPE"    sigFPE    :: CInt
-foreign import ccall "__hsposix_SIGHUP"    sigHUP    :: CInt
-foreign import ccall "__hsposix_SIGILL"    sigILL    :: CInt
-foreign import ccall "__hsposix_SIGINT"    sigINT    :: CInt
-foreign import ccall "__hsposix_SIGKILL"   sigKILL   :: CInt
-foreign import ccall "__hsposix_SIGPIPE"   sigPIPE   :: CInt
-foreign import ccall "__hsposix_SIGQUIT"   sigQUIT   :: CInt
-foreign import ccall "__hsposix_SIGSEGV"   sigSEGV   :: CInt
-foreign import ccall "__hsposix_SIGSTOP"   sigSTOP   :: CInt
-foreign import ccall "__hsposix_SIGTERM"   sigTERM   :: CInt
-foreign import ccall "__hsposix_SIGTSTP"   sigTSTP   :: CInt
-foreign import ccall "__hsposix_SIGTTIN"   sigTTIN   :: CInt
-foreign import ccall "__hsposix_SIGTTOU"   sigTTOU   :: CInt
-foreign import ccall "__hsposix_SIGUSR1"   sigUSR1   :: CInt
-foreign import ccall "__hsposix_SIGUSR2"   sigUSR2   :: CInt
-foreign import ccall "__hsposix_SIGPOLL"   sigPOLL   :: CInt
-foreign import ccall "__hsposix_SIGPROF"   sigPROF   :: CInt
-foreign import ccall "__hsposix_SIGSYS"    sigSYS    :: CInt
-foreign import ccall "__hsposix_SIGTRAP"   sigTRAP   :: CInt
-foreign import ccall "__hsposix_SIGURG"    sigURG    :: CInt
-foreign import ccall "__hsposix_SIGVTALRM" sigVTALRM :: CInt
-foreign import ccall "__hsposix_SIGXCPU"   sigXCPU   :: CInt
-foreign import ccall "__hsposix_SIGXFSZ"   sigXFSZ   :: CInt
+#ifdef __HUGS__
+sigABRT   = (#const SIGABRT)   :: CInt
+sigALRM   = (#const SIGALRM)   :: CInt
+sigBUS    = (#const SIGBUS)    :: CInt
+sigCHLD   = (#const SIGCHLD)   :: CInt
+sigCONT   = (#const SIGCONT)   :: CInt
+sigFPE    = (#const SIGFPE)    :: CInt
+sigHUP    = (#const SIGHUP)    :: CInt
+sigILL    = (#const SIGILL)    :: CInt
+sigINT    = (#const SIGINT)    :: CInt
+sigKILL   = (#const SIGKILL)   :: CInt
+sigPIPE   = (#const SIGPIPE)   :: CInt
+sigQUIT   = (#const SIGQUIT)   :: CInt
+sigSEGV   = (#const SIGSEGV)   :: CInt
+sigSTOP   = (#const SIGSTOP)   :: CInt
+sigTERM   = (#const SIGTERM)   :: CInt
+sigTSTP   = (#const SIGTSTP)   :: CInt
+sigTTIN   = (#const SIGTTIN)   :: CInt
+sigTTOU   = (#const SIGTTOU)   :: CInt
+sigUSR1   = (#const SIGUSR1)   :: CInt
+sigUSR2   = (#const SIGUSR2)   :: CInt
+#ifdef SIGPOLL
+sigPOLL   = (#const SIGPOLL)   :: CInt
+#endif
+sigPROF   = (#const SIGPROF)   :: CInt
+sigSYS    = (#const SIGSYS)    :: CInt
+sigTRAP   = (#const SIGTRAP)   :: CInt
+sigURG    = (#const SIGURG)    :: CInt
+sigVTALRM = (#const SIGVTALRM) :: CInt
+sigXCPU   = (#const SIGXCPU)   :: CInt
+sigXFSZ   = (#const SIGXFSZ)   :: CInt
+#else
+foreign import ccall unsafe "__hsposix_SIGABRT"   sigABRT   :: CInt
+foreign import ccall unsafe "__hsposix_SIGALRM"   sigALRM   :: CInt
+foreign import ccall unsafe "__hsposix_SIGBUS"    sigBUS    :: CInt
+foreign import ccall unsafe "__hsposix_SIGCHLD"   sigCHLD   :: CInt
+foreign import ccall unsafe "__hsposix_SIGCONT"   sigCONT   :: CInt
+foreign import ccall unsafe "__hsposix_SIGFPE"    sigFPE    :: CInt
+foreign import ccall unsafe "__hsposix_SIGHUP"    sigHUP    :: CInt
+foreign import ccall unsafe "__hsposix_SIGILL"    sigILL    :: CInt
+foreign import ccall unsafe "__hsposix_SIGINT"    sigINT    :: CInt
+foreign import ccall unsafe "__hsposix_SIGKILL"   sigKILL   :: CInt
+foreign import ccall unsafe "__hsposix_SIGPIPE"   sigPIPE   :: CInt
+foreign import ccall unsafe "__hsposix_SIGQUIT"   sigQUIT   :: CInt
+foreign import ccall unsafe "__hsposix_SIGSEGV"   sigSEGV   :: CInt
+foreign import ccall unsafe "__hsposix_SIGSTOP"   sigSTOP   :: CInt
+foreign import ccall unsafe "__hsposix_SIGTERM"   sigTERM   :: CInt
+foreign import ccall unsafe "__hsposix_SIGTSTP"   sigTSTP   :: CInt
+foreign import ccall unsafe "__hsposix_SIGTTIN"   sigTTIN   :: CInt
+foreign import ccall unsafe "__hsposix_SIGTTOU"   sigTTOU   :: CInt
+foreign import ccall unsafe "__hsposix_SIGUSR1"   sigUSR1   :: CInt
+foreign import ccall unsafe "__hsposix_SIGUSR2"   sigUSR2   :: CInt
+#ifdef SIGPOLL
+foreign import ccall unsafe "__hsposix_SIGPOLL"   sigPOLL   :: CInt
+#endif
+foreign import ccall unsafe "__hsposix_SIGPROF"   sigPROF   :: CInt
+foreign import ccall unsafe "__hsposix_SIGSYS"    sigSYS    :: CInt
+foreign import ccall unsafe "__hsposix_SIGTRAP"   sigTRAP   :: CInt
+foreign import ccall unsafe "__hsposix_SIGURG"    sigURG    :: CInt
+foreign import ccall unsafe "__hsposix_SIGVTALRM" sigVTALRM :: CInt
+foreign import ccall unsafe "__hsposix_SIGXCPU"   sigXCPU   :: CInt
+foreign import ccall unsafe "__hsposix_SIGXFSZ"   sigXFSZ   :: CInt
+#endif /* __HUGS__ */
 
 internalAbort ::Signal
 internalAbort = sigABRT
@@ -136,10 +193,8 @@ busError = sigBUS
 processStatusChanged :: Signal
 processStatusChanged = sigCHLD
 
-#ifndef cygwin32_TARGET_OS
 continueProcess :: Signal
 continueProcess = sigCONT
-#endif
 
 floatingPointException :: Signal
 floatingPointException = sigFPE
@@ -186,8 +241,10 @@ userDefinedSignal1 = sigUSR1
 userDefinedSignal2 :: Signal
 userDefinedSignal2 = sigUSR2
 
+#ifdef SIGPOLL
 pollableEvent :: Signal
 pollableEvent = sigPOLL
+#endif
 
 profilingTimerExpired :: Signal
 profilingTimerExpired = sigPROF
@@ -230,13 +287,20 @@ foreign import ccall unsafe "killpg"
 raiseSignal :: Signal -> IO ()
 raiseSignal sig = throwErrnoIfMinus1_ "raiseSignal" (c_raise sig)
 
+#if defined(__GLASGOW_HASKELL__) && (defined(openbsd_TARGET_OS) || defined(freebsd_TARGET_OS))
+foreign import ccall unsafe "genericRaise"
+  c_raise :: CInt -> IO CInt
+#else
 foreign import ccall unsafe "raise"
   c_raise :: CInt -> IO CInt
+#endif
 
+#ifdef __GLASGOW_HASKELL__
 data Handler = Default
              | Ignore
             -- not yet: | Hold 
              | Catch (IO ())
+             | CatchOnce (IO ())
 
 installHandler :: Signal
                -> Handler
@@ -259,24 +323,35 @@ installHandler int handler maybe_mask = do
       rc <- case handler of
              Default -> stg_sig_install int (#const STG_SIG_DFL) p_sp mask
              Ignore  -> stg_sig_install int (#const STG_SIG_IGN) p_sp mask
-             Catch m -> do sptr <- newStablePtr m
-                           poke p_sp sptr
-                           stg_sig_install int (#const STG_SIG_HAN) p_sp mask 
+             Catch m -> install'' m p_sp mask int (#const STG_SIG_HAN)
+             CatchOnce m -> install'' m p_sp mask int (#const STG_SIG_RST)
 
       case rc of
        (#const STG_SIG_DFL) -> return Default
        (#const STG_SIG_IGN) -> return Ignore
        (#const STG_SIG_ERR) -> throwErrno "installHandler"
        (#const STG_SIG_HAN) -> do
-               osptr <- peek p_sp
-               m     <- deRefStablePtr osptr
+               m <- peekHandler p_sp
                return (Catch m)
+       (#const STG_SIG_RST) -> do
+               m <- peekHandler p_sp
+               return (CatchOnce m)
+
+    install'' m p_sp mask int reset = do
+      sptr <- newStablePtr m
+      poke p_sp sptr
+      stg_sig_install int reset p_sp mask
+
+    peekHandler p_sp = do
+      osptr <- peek p_sp
+      deRefStablePtr osptr
 
 foreign import ccall unsafe
   stg_sig_install :: CInt -> CInt -> Ptr (StablePtr (IO ())) -> Ptr CSigset
         -> IO CInt
 
-#endif // !__PARALLEL_HASKELL__
+#endif /* !__PARALLEL_HASKELL__ */
+#endif /* __GLASGOW_HASKELL__ */
 
 -- -----------------------------------------------------------------------------
 -- Alarms
@@ -289,6 +364,27 @@ scheduleAlarm secs = do
 foreign import ccall unsafe "alarm"
   c_alarm :: CUInt -> IO CUInt
 
+#ifdef __GLASGOW_HASKELL__
+-- -----------------------------------------------------------------------------
+-- The NOCLDSTOP flag
+
+foreign import ccall "&nocldstop" nocldstop :: Ptr Int
+
+-- | Tells the system whether or not to set the @SA_NOCLDSTOP@ flag when
+-- installing new signal handlers.
+setStoppedChildFlag :: Bool -> IO Bool
+setStoppedChildFlag b = do
+    rc <- peek nocldstop
+    poke nocldstop $ fromEnum (not b) 
+    return (rc == (0::Int))
+
+-- | Queries the current state of the stopped child flag.
+queryStoppedChildFlag :: IO Bool
+queryStoppedChildFlag = do
+    rc <- peek nocldstop
+    return (rc == (0::Int))
+#endif /* __GLASGOW_HASKELL__ */
+
 -- -----------------------------------------------------------------------------
 -- Manipulating signal sets
 
@@ -335,7 +431,7 @@ getSignalMask :: IO SignalSet
 getSignalMask = do
   fp <- mallocForeignPtrBytes sizeof_sigset_t
   withForeignPtr fp $ \p ->
-    throwErrnoIfMinus1_ "getSignalMask" (c_sigprocmask 0 p nullPtr)
+    throwErrnoIfMinus1_ "getSignalMask" (c_sigprocmask 0 nullPtr p)
   return (SignalSet fp)
    
 sigProcMask :: String -> CInt -> SignalSet -> IO ()
@@ -375,6 +471,16 @@ foreign import ccall unsafe "sigsuspend"
   c_sigsuspend :: Ptr CSigset -> IO CInt
 #endif
 
+#ifdef __HUGS__
+foreign import ccall unsafe "sigdelset"
+  c_sigdelset   :: Ptr CSigset -> CInt -> IO CInt
+
+foreign import ccall unsafe "sigfillset"
+  c_sigfillset  :: Ptr CSigset -> IO CInt
+
+foreign import ccall unsafe "sigismember"
+  c_sigismember :: Ptr CSigset -> CInt -> IO CInt
+#else
 foreign import ccall unsafe "__hscore_sigdelset"
   c_sigdelset   :: Ptr CSigset -> CInt -> IO CInt
 
@@ -383,10 +489,20 @@ foreign import ccall unsafe "__hscore_sigfillset"
 
 foreign import ccall unsafe "__hscore_sigismember"
   c_sigismember :: Ptr CSigset -> CInt -> IO CInt
+#endif /* __HUGS__ */
 
 foreign import ccall unsafe "sigpending"
   c_sigpending :: Ptr CSigset -> IO CInt
 
+#ifdef __HUGS__
+c_SIG_BLOCK   = (#const SIG_BLOCK)   :: CInt
+c_SIG_SETMASK = (#const SIG_SETMASK) :: CInt
+c_SIG_UNBLOCK = (#const SIG_UNBLOCK) :: CInt
+#else
 foreign import ccall unsafe "__hsposix_SIG_BLOCK"   c_SIG_BLOCK   :: CInt
 foreign import ccall unsafe "__hsposix_SIG_SETMASK" c_SIG_SETMASK :: CInt
 foreign import ccall unsafe "__hsposix_SIG_UNBLOCK" c_SIG_UNBLOCK :: CInt
+#endif /* __HUGS__ */
+
+#endif /* mingw32_TARGET_OS */
+