[GHC] #14621: GHC 8.2 GCed too early
GHC
ghc-devs at haskell.org
Thu Dec 28 10:31:23 UTC 2017
#14621: GHC 8.2 GCed too early
-------------------------------------+-------------------------------------
Reporter: kazu-yamamoto | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.2.2
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
The network package uses mkWeakVar so that unreachable Sockets can be
GCed. See the master branch of https://github.com/haskell/network
{{{
mkSocket :: CInt
-> Family
-> SocketType
-> ProtocolNumber
-> SocketStatus
-> IO Socket
mkSocket fd fam sType pNum stat = do
mStat <- newMVar stat
withSocketsDo $ return ()
let sock = Socket fd fam sType pNum mStat
##if MIN_VERSION_base(4,6,0)
_ <- mkWeakMVar mStat $ close sock
##endif
return sock
}}}
The following code cause "threadWait: invalid argument (Bad file
descriptor)" in accept:
{{{
module Main where
import Control.Concurrent (forkIO)
import Control.Monad (void, forever)
import Network.Socket hiding (recv)
import Network.Socket.ByteString (recv, sendAll)
main :: IO ()
main = do
let localhost = "localhost"
listenPort = "9876"
connectPort = "6789"
proxy localhost listenPort connectPort
proxy :: HostName -> ServiceName -> ServiceName -> IO ()
proxy localhost listenPort connectPort = do
fromClient <- serverSocket localhost listenPort
toServer <- clientSocket localhost connectPort
void $ forkIO $ relay toServer fromClient
relay fromClient toServer
relay :: Socket -> Socket -> IO ()
relay s1 s2 = forever $ do
payload <- recv s1 4096
sendAll s2 payload
serverSocket :: HostName -> ServiceName -> IO Socket
serverSocket host port = do
let hints = defaultHints {
addrFlags = [AI_PASSIVE]
, addrSocketType = Stream
}
addr:_ <- getAddrInfo (Just hints) (Just host) (Just port)
sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol
addr)
bind sock (addrAddress addr)
listen sock 1
fst <$> accept sock
clientSocket :: HostName -> ServiceName -> IO Socket
clientSocket host port = do
let hints = defaultHints { addrSocketType = Stream }
addr:_ <- getAddrInfo (Just hints) (Just host) (Just port)
sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol
addr)
connect sock (addrAddress addr)
return sock
}}}
GC frees sock while accepting. This occurs with GHC 8.2 or higher.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14621>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list