-- thread A
t <- forkIO $ do
_ <- accept listener -- blocks
-- thread B
killThread t
适用于 Linux(可能也适用于 OS X 和 FreeBSD)但不适用于 Windows(尝试使用 +RTS -N4 -RTS 等进行线程化)。
A
在这种情况下? A
在一种特殊模式下,它允许在 accept
上阻塞的点终止? A
会有帮助吗?与 forkOS
fork 而不是 forkIO
? 仅当 bug report 发出警报时,我才注意到这种异常的 Windows 行为。 .
最佳答案
有趣的问题!
你不能中断阻塞的外部调用,所以我有点惊讶你能够中断 Linux 上的线程。另外,forkOS
没有帮助 - 只是让外部代码分配线程本地存储,但与阻塞行为无关。但请记住,accept 可以设置为非阻塞:
If no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present. If the socket is marked nonblocking and no pending connections are present on the queue, accept() fails with the error EAGAIN or EWOULDBLOCK.
做了什么in the Network library for Posix systems.这将允许
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.
现在,在 Windows 上接受 -thread 运行时,使用 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
自 2005 年以来,
network
的版本包,在带有 -thread 的 Windows 上显式使用标记为 safe
的接受调用,允许其他线程取得进展,但不将套接字本身设置为非阻塞模式(因此调用线程阻塞)。要解决它,我看到两个选项:
关于multithreading - 在 Windows 上等待 Network.Socket.accept 的 Haskell 或 Haskell OS 线程能否被杀死?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10608602/