Opened 5 years ago

Closed 5 years ago

#4078 closed bug (fixed)

hReady and hWaitForInput block under Windows

Reported by: tbogdala Owned by: simonmar
Priority: normal Milestone: 6.12.3
Component: libraries/base Version: 6.12.1
Keywords: hReady hWaitForInput Windows blocking Cc:
Operating System: Windows Architecture: x86_64 (amd64)
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description

While using a Network.Socket converted to a Handle with socketToHandle, calling hReady or hWaitForInput on that handle will block.

This happens within ghci or when compiled with -threaded and executed with "+RTS -N2 -RTS" options.

I've attached a simple server.hs file that listens on a port. Once a client connects it loops until hReady returns true - then it will read from the port. Load it in gchi and execute something like:

servNumber "11333"

I've also attached a quick client.hs module to load in ghci to send data to the port. Load it in ghci and execute something like:

s1 <- openServer "localhost" "11333"
write2Server "blash" s1

Here's the code.

server.hs

import Network.Socket
import Control.Concurrent
import System.IO

-- main = servNumber "11333"

servNumber :: String -> IO ()
servNumber port = withSocketsDo $ do
  addrInfos <- getAddrInfo 
                    (Just (defaultHints {addrFlags = [AI_PASSIVE]}))
                    Nothing (Just port)
  let serveraddr = head addrInfos
  sock <- socket (addrFamily serveraddr) Stream defaultProtocol
  bindSocket sock (addrAddress serveraddr)
  listen sock 5
  procIncoming sock
 where
  procIncoming :: Socket -> IO ()
  procIncoming masterSock = do
    (conSock, _) <- accept masterSock
    forkIO $ doWork conSock
    procIncoming masterSock 

  doWork :: Socket -> IO ()
  doWork conSock = do
    h <- socketToHandle conSock ReadWriteMode
    hSetBuffering h LineBuffering
    loop h 

  loop :: Handle -> IO ()
  loop h = do 
    putStrLn "Calling hReady."
    ready <- hReady h
    --ready <- hWaitForInput h 1
    if ready 
        then hGetLine h >>= putStrLn >> loop h
        else loop h 

client.hs

import Network.Socket
import Control.Concurrent
import System.IO


openServer :: String -> String -> IO (Handle)
openServer hostname port = withSocketsDo $ do
  addrinfos <- getAddrInfo Nothing (Just hostname) (Just port)
  let serveraddr = head addrinfos
  sock <- socket (addrFamily serveraddr) Stream defaultProtocol
  connect sock (addrAddress serveraddr)
  h <- socketToHandle sock ReadWriteMode
  hSetBuffering h LineBuffering
  return h

write2Server :: String -> Handle -> IO ()
write2Server msg h = do
  hPutStrLn h msg
  hFlush h

closeServer :: Handle -> IO ()
closeServer h = hClose h

Change History (5)

comment:1 Changed 5 years ago by tbogdala

I forgot to mention that this is on Windows 7 with Haskell Platform 2010.1.0.0.

comment:2 Changed 5 years ago by tbogdala

  • Summary changed from hReady and h hWaitForInput block under Windows to hReady and hWaitForInput block under Windows

comment:3 Changed 5 years ago by simonmar

  • Milestone set to 6.12.3
  • Owner set to simonmar

I believe this is supposed to work.

comment:4 Changed 5 years ago by simonmar

  • Status changed from new to merge

Fixed:

Mon May 17 14:37:41 BST 2010  Simon Marlow <[email protected]>
  * hWaitForInput: don't try to read from the device (#4078)
  readTextDeviceNonBlocking is not non-blocking on Windows

comment:5 Changed 5 years ago by igloo

  • Resolution set to fixed
  • Status changed from merge to closed

Merged.

Note: See TracTickets for help on using tickets.