Repository navigation
send == 0: how to wait for socket to drain? #320
Description
Activity
Hmm, this would possibly require dropping down to
GHC.Primand usingwaitWrite#on theSocketfile descriptor.@bscottm Are you able to produce a minimal test case for this failure?
@eborden: I'll see what I can craft... Probably the best test case would be to take the
echoserver and send 66Kb buffers (at least for MacOS -- localhost/::1 buffering is 64Kb.)Receiver side is a bit trickier because the receiver's call to
recvneeds to consume less than 64kb at a time. In the SublimeHaskell plugin, the receiver consumes 10Kb at a time, looking for a newline (it's a JSON stream, newline is the separator between responses...)/cc @mvoidex
Reacted by Evan Rutledge BordenWhat about this?
sendAll :: Socket -- ^ Connected socket -> ByteString -- ^ Data to send -> IO () sendAll sock bs | B.null bs = return () | otherwise = do sent <- send sock bs if sent == 0 then do threadWaitWrite $ fromIntegral $ sockFd sock sendAll sock bs else if sent > 0 then sendAll sock (B.drop sent bs) else return ()
I have not been able to successfully reproduce the
send == 0issue.@bscottm Thanks!
I will merge this into each versions.-
sendAll -
sendAllTo -
sendMany -
sendManyTo -
sendAllfor Lazy
-
I did many
git push -f. Sorry for your confusion.- added a commit that references this issue
on May 25, 2018 fixed via #321
I ran into this particular problem in @mvoidex's
hsdevserver while tracking down whyhsdevwould send incomplete responses. I was able to track the problem down to a reimplementation ofsendAll:The subtle bug in this code is the
send > 0:sendcan return 0 because the OS is waiting for a buffer to drain and the underlying descriptors are in non-blocking mode (GHC runtime "feature".)One way around the
send == 0issue is to callControl.Concurrent.threadDelay. Optimally, you'd really want to callControl.Concurrent.threadWaitWrite, but you can't because converting the socket to a file descriptor is a one way process.Is there a way to call
threadWaitWritewithout converting the socket to a descriptor?