微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

多线程 – 可以在Windows上等待Network.Socket.accept的Haskell或Haskell OS线程吗?

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

在Linux上(可能也在OS X和FreeBSD上),但不在Windows上(使用RTS -N4 -RTS等等).

>在这种情况下终止线程A的正确方法是什么?
>有没有一种方式来将线程A分叉到一个特殊的模式,允许终止在它阻止接受的点?
>如果A用forkOS而不是forkIO分叉,会有帮助吗?

我注意到这个错误的Windows行为只有当一个bug report警告.

解决方法

有趣的问题!

你不能中断阻止外来电话,所以我有点惊讶,你可以在Linux上中断线程.而且,forkOS没有帮助 – 只允许外部代码分配线程本地存储,但与阻止行为无关.但是回想一下接受可以设置为无阻塞:

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.这样就允许接受中断.

关于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上接受运行时的线程,使用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年以来,在Windows上使用-threaded的版本显式地使用了一个标记为安全的接受调用,允许其他线程取得进展,但不将套接字本身设置为非阻塞模式(因此调用线程阻塞).

解决它,我看到两个选项:

>制定如何在Windows上进行非阻塞接受呼叫,并修补网络库 – 查看例如snap或yesod在这里,看看他们是否已经解决了.>使用某种监控线程伪造epoll,监控被阻止的子线程进度.

原文地址:https://www.jb51.cc/java/122352.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐