multithreading - 在 Windows 上等待 Network.Socket.accept 的 Haskell 或 Haskell OS 线程能否被杀死?

标签 multithreading exception networking haskell asynchronous

-- thread A
t <- forkIO $ do
   _ <- accept listener -- blocks
-- thread B
killThread t

适用于 Linux(可能也适用于 OS X 和 FreeBSD)但不适用于 Windows(尝试使用 +RTS -N4 -RTS 等进行线程化)。
  • 终止线程的正确方法是什么 A在这种情况下?
  • 有没有办法 fork 线程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 的接受调用,允许其他线程取得进展,但不将套接字本身设置为非阻塞模式(因此调用线程阻塞)。

    要解决它,我看到两个选项:
  • 弄清楚如何在 Windows 上进行非阻塞接受调用,并修补网络库——看看例如什么snap 或 yesod 在这里做,看看他们是否已经解决了。
  • 使用某种监督线程来伪造 epoll,监视阻塞的子线程的进度。
  • 关于multithreading - 在 Windows 上等待 Network.Socket.accept 的 Haskell 或 Haskell OS 线程能否被杀死?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10608602/

    相关文章:

    exception - 如何在运行 10.5 的 Mac OS X 10.6 上构建 PyObjC 项目?

    java - java MDB 中处理异常的最佳方法是什么?

    c++ - 网络库 + 助手 (c++)

    multithreading - node.js 应用程序中单进程中的多线程 socket.io

    c - 通过递归函数泄漏线程

    c++ - 我应该在 C++ 中使用异常说明符吗?

    linux - 如何使用 telnet 获取外部连接的 IP,或者可能是 memcached 允许的 ip 的配置错误

    c++ - 网络延迟和Application-> ProcessMessages()

    c++ - 当我们使用 CTRL + Break 中断时如何在 WinDbg 中查看真实的调用堆栈

    c++ - 如何从一个 UDP 套接字处理多个客户端?