`getErrno` and threads

The documentation for getErrno says:

Get the current errno value in the current thread.

I donโ€™t understand if this means the current OS thread. In particular, is threaded errno runtime extracted when a Haskell thread is transferred from one OS thread to another?

This question seems to be related, but it is not clear to me whether this refers to OS threads or Haskell.

+8
multithreading haskell ghc errno
source share
1 answer

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 ).

+7
source share

All Articles