For the latest versions of GHC, at least the runtime saves errno in the Thread Storage Object ( TSO ) and takes control of it when transferring the execution thread to another OS thread. This means that it is safe to rely on errno in the unbound ( forkIO ) and bound ( forkOS ) forkOS . Here is a test for Linux:
err.hs
import Control.Concurrent import Control.Exception import Foreign.C foreign import ccall safe get_ostid :: IO CUInt foreign import ccall safe sleep :: CUInt -> IO CUInt foreign import ccall unsafe get_errno :: IO CInt foreign import ccall unsafe set_errno :: CInt -> IO () forkIO' f = do done <- newEmptyMVar forkIO (f `finally` putMVar done ()) return (takeMVar done) prefix = do id <- get_ostid return $ show id ++ ": " main = do wait <- forkIO' $ do -- spawn a lightweight thread errno <- get_errno (putStr =<< prefix) >> putStrLn ("outer errno is " ++ show errno) (putStr =<< prefix) >> putStrLn "Setting outer errno to 3" set_errno 3 wait' <- forkIO' $ do -- spawn another lightweight thread errno <- get_errno (putStr =<< prefix) >> putStrLn ("inner errno is " ++ show errno) (putStr =<< prefix) >> putStrLn "Setting inner errno to 2" set_errno 2 sleep 2 -- force this lightweight thread to tie up the OS thread errno <- get_errno (putStr =<< prefix) >> putStrLn ("inner errno is " ++ show errno) threadDelay 1000000 -- wait a second -- By now, we should be in another OS thread. errno <- get_errno (putStr =<< prefix) >> putStrLn ("outer errno is " ++ show errno) wait' wait
err.c
#include <errno.h> #include <sys/syscall.h> #include <unistd.h> int get_errno(void) { return errno; } void set_errno(int e) { errno = e; } unsigned get_ostid(void) { return syscall(SYS_gettid); }
Compile with:
ghc -o err -threaded err.hs err.c
And the result should look something like this:
12282: outer errno is 0 12282: Setting outer errno to 3 12282: inner errno is 0 12282: Setting inner errno to 2 12283: outer errno is 3 12282: inner errno is 2
OS thread IDs are printed at the beginning of each line. Note that errno from 3 was moved to the second OS thread ( 12283 ).
jekor
source share