
Hi, I recently spent a while debugging a problem where a program deadlocked in the non-threaded runtime, but ran fine in the threaded runtime, despite the program having no blocking FFI calls, and boiled it down to the following test case: module Main(main) where import System import System.IO import System.Process main = do (ih, oh, _, _) <- runInteractiveProcess "cat" [] Nothing Nothing comphszp <- hGetContents oh print (length comphszp) -- hClose ih -- with this line they both deadlock The reason for the deadlock is fairly straightforward; since ih isn't closed before comphszp is fully demanded, no progress can be made. My guess is that the threaded runtime is fine because ih is dead at that point, and the finalizer for ih gets a chance to run, closing ih. If I'm right, is it really sensible for every handle to have this finalizer? Closing a pipe has externally visible side effects beyond just the release of resources, so it doesn't seem like it should happen non-deterministically. Cheers, Ganesh