
Simon Marlow wrote (snipped)
Hmm. I rather think that hGetChar should always return a character immediately if there is one available, regardless of the buffering mode. Looking at the source, it appears that hGetLine behaves like this, as does lazy reading with hGetContents. I can't see any reason for waiting for the buffer to be completely full before returning anything.
If you have a source tree handy, try the enclosed patch. If not, make a copy of hGetChar from the sources in libraries/base/GHC/IO.hs, apply the patch, and compile it separately (you'll need to import GHC.Handle explicitly, amongst other things). OK, applying the patch and dropping the patched hGetChar in (as per the attached file) seems to fix the problem. Is there any way of getting the same effect without setting NoBuffering/waiting for the next ghc release/changing every call by client and server to hGetChar in the program? If not I think I'll keep NoBuffering and wait for the next ghc release ..
Thanks, George -- Test program for server using GHC Socket library. module Main(main) where import GHC.Enum import GHC.Base import GHC.IOBase import GHC.Handle -- much of the real stuff is in here import GHC.Real import GHC.Num import GHC.Show import GHC.List import GHC.Exception ( ioError, catch ) import GHC.Conc import IO import Network main = do socket <- listenOn (PortNumber 15151) (handle,hostName,_) <- accept socket hSetBuffering handle (BlockBuffering (Just 4096)) putStr ("Accepted: "++hostName++"\n") c <- new_hGetChar handle putStrLn (show c) new_hGetChar :: Handle -> IO Char new_hGetChar handle = wantReadableHandle "hGetChar" handle $ \handle_ -> do let fd = haFD handle_ ref = haBuffer handle_ buf <- readIORef ref if not (bufferEmpty buf) then hGetcBuffered fd ref buf else do -- buffer is empty. case haBufferMode handle_ of LineBuffering -> do new_buf <- fillReadBuffer fd True (haIsStream handle_) buf hGetcBuffered fd ref new_buf BlockBuffering _ -> do new_buf <- fillReadBuffer fd True (haIsStream handle_) buf hGetcBuffered fd ref new_buf NoBuffering -> error "This can't happen" {- do -- make use of the minimal buffer we already have let raw = bufBuf buf r <- readRawBuffer "hGetChar" (fromIntegral fd) (haIsStream handle_) raw 0 1 if r == 0 then ioe_EOF else do (c,_) <- readCharFromBuffer raw 0 return c -} hGetcBuffered fd ref buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w } = do (c,r) <- readCharFromBuffer b r let new_buf | r == w = buf{ bufRPtr=0, bufWPtr=0 } | otherwise = buf{ bufRPtr=r } writeIORef ref new_buf return c