Killing a thread waiting on hGetLine from a socket (Windows)

Viewed 105

If I run the following Java program on a Windows (10) machine (I'm posting the program here for the sake of completeness):

public class IdleServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        ServerSocket serverSock = new ServerSocket(9090);

        Socket sock = serverSock.accept();

        while (true) Thread.sleep(1000);
    }
}

and then I connect to the Java server from Haskell:

readWithinNSecs :: IO ()
readWithinNSecs = withSocketsDo $ do
  h <- connectTo "localhost" (PortNumber 9090)
  hSetBuffering h NoBuffering
  readerTid <- forkIO $ reader h
  threadDelay $ 2 * 10^6
  putStrLn "Killing the reader"
  killThread readerTid
  putStrLn "Reader thread killed"
  where
    reader h = do
      line <- strip <$> hGetLine h
      putStrLn $ "Got " ++ line

then the Haskell program will hang when trying to kill the process that is trying to read from the handle. Killing the Java server will cause the Haskell program to terminate, giving also the error:

<socket: 380>: hGetLine: failed (No error)

If I run the same two programs on Linux then the Haskell program terminates.

This seems to point to a bug in the base libraries of Haskell, so I reported it, but in the meantime I need to find a way to workaround this. Any ideas?

UPDATE: I posted the solution below, but it is not satisfactory: it terminates the reader thread, but it leaks resources.

import           Control.Concurrent.Async

-- ...

readerAsync h = do
  a <- async $ strip <$> hGetLine h
  line <- wait a
  putStrLn $ "Got " ++ line
0 Answers
Related