, . . - - .
import unsafe, , (. @carl). , unsafe. , :
foreign import ccall unsafe "wiring.h delay" c_delay :: CUInt -> IO ()
, , GHC FFI . .
, , ( , GHC 7.4+, ). :
http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Signals
: Signal handling differs between the threaded version of the runtime and the non-threaded version.
1 - FFI:
, . Linux 2.6.18 ghc 7.6.1.
C-:
#include <unistd.h>
#include <stdio.h>
#include <time.h>
unsigned delay(unsigned sec)
{
struct timespec req={0};
req.tv_sec = sec;
req.tv_nsec = 0;
while (nanosleep(&req, &req) == -1) {
printf("Got interrupt, continuing\n");
continue;
}
return 1;
}
Haskell:
{-
-- Filename Test.hs
module Main (main) where
import Foreign.C.Types
foreign import ccall safe "delay" delay :: CUInt -> IO CUInt
main = do
putStrLn "Sleeping"
n <- delay 2000
putStrLn $ "Got return code from sleep: " ++ show n
, ghc 7.6.1 (: ghc Test.hs ctest.c), , :
./Test
Sleeping
Got interrupt, continuing
Got interrupt, continuing
Got interrupt, continuing
Got interrupt, continuing
....
....
Got return code from sleep: 1
2 - SIGVTALRM FFI :
, SIGVTALRM. , SIGVTALRM FFI, FFI. , FFI (, SIGVTALRM ).
{-
-- Test.hs
module Main (main) where
import Foreign.C.Types
import System.Posix.Signals
foreign import ccall safe "delay" delay :: CUInt -> IO CUInt
main = do
putStrLn "Sleeping"
-- Block SIGVTALRM temporarily to avoid interrupts while sleeping
blockSignals $ addSignal sigVTALRM emptySignalSet
n <- delay 2
putStrLn $ "Got return code from sleep: " ++ show n
-- Unblock SIGVTALRM
unblockSignals $ addSignal sigVTALRM emptySignalSet
return ()