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