Cet*_*ert 9 networking multithreading haskell asynchronous exception
-- thread A
t <- forkIO $ do
_ <- accept listener -- blocks
Run Code Online (Sandbox Code Playgroud)
-- thread B
killThread t
Run Code Online (Sandbox Code Playgroud)
适用于Linux(可能也适用于OS X和FreeBSD),但不适用于Windows(尝试使用+ RTS -N4 -RTS等).
A在这种情况下终止线程的正确方法是什么?A在特殊模式下分叉线程,允许在它阻塞的点终止accept?A分叉forkOS而不是forkIO?只有在通过错误报告提醒时,我才注意到这种不正常的Windows行为.
Don*_*art 13
有趣的问题!
你不能打断阻止外部调用,所以我有点惊讶你能够在Linux上中断线程.此外,forkOS没有帮助 - 只是让外国代码分配线程本地存储,但与阻止行为无关.但请记住,接受可以设置为非阻塞:
如果队列中没有挂起的连接,并且套接字未标记为非阻塞,则accept()会阻止调用方,直到存在连接.如果套接字标记为非阻塞且队列中没有挂起的连接,则accept()将失败,并显示错误EAGAIN或EWOULDBLOCK.
这是在Posix系统的网络库中完成的操作.然后这允许accept被中断.
有关Windows的有趣说明:
-- On Windows, our sockets are not put in non-blocking mode (non-blocking
-- is not supported for regular file descriptors on Windows, and it would
-- be a pain to support it only for sockets). So there are two cases:
--
-- - the threaded RTS uses safe calls for socket operations to get
-- non-blocking I/O, just like the rest of the I/O library
--
-- - with the non-threaded RTS, only some operations on sockets will be
-- non-blocking. Reads and writes go through the normal async I/O
-- system. accept() uses asyncDoProc so is non-blocking. A handful
-- of others (recvFrom, sendFd, recvFd) will block all threads - if this
-- is a problem, -threaded is the workaround.
Run Code Online (Sandbox Code Playgroud)
现在,使用-threaded运行时在Windows上接受使用accept_safe(允许其他线程进行) - 但它不会将套接字置于非阻塞模式:
accept sock@(MkSocket s family stype protocol status) = do
currentStatus <- readMVar status
okay <- sIsAcceptable sock
if not okay
then
ioError (userError ("accept: can't perform accept on socket (" ++ (show (family,stype,protocol)) ++") in status " ++
show currentStatus))
else do
let sz = sizeOfSockAddrByFamily family
allocaBytes sz $ \ sockaddr -> do
#if defined(mingw32_HOST_OS) && defined(__GLASGOW_HASKELL__)
new_sock <-
if threaded
then with (fromIntegral sz) $ \ ptr_len ->
throwErrnoIfMinus1Retry "Network.Socket.accept" $
c_accept_safe s sockaddr ptr_len
else do
paramData <- c_newAcceptParams s (fromIntegral sz) sockaddr
rc <- asyncDoProc c_acceptDoProc paramData
new_sock <- c_acceptNewSock paramData
c_free paramData
when (rc /= 0)
(ioError (errnoToIOError "Network.Socket.accept" (Errno (fromIntegral rc)) Nothing Nothing))
return new_sock
Run Code Online (Sandbox Code Playgroud)
自2005年以来network,在带有-threaded的Windows 上的软件包版本显式使用标记为的accept调用safe,允许其他线程进行,但不将套接字本身设置为非阻塞模式(因此调用线程阻塞).
要解决它,我看到两个选项: