文档getErrno
内容如下:
获取当前线程中errno的当前值。
我不清楚这是否意味着当前的操作系统线程。特别是,errno
当 Haskell 线程从一个 OS 线程迁移到另一个时,(线程)运行时是否会获取并隐藏?
这个问题似乎是相关的,但我不清楚那里所说的是否与操作系统或 Haskell 线程有关。
至少对于最新版本的 GHC,运行时保存errno
在线程存储对象 ( TSO
) 中,并在将运行时线程迁移到另一个 OS 线程时负责管理它。errno
这意味着在 unbound ( forkIO
) 和 bound ( forkOS
) 线程中依赖应该是安全的。这是针对 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);
}
编译:
ghc -o err -threaded err.hs err.c
结果应该类似于:
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
操作系统线程 ID 打印在每行的开头。请注意,errno
已3
迁移到第二个 OS 线程 ( 12283
)。