fpco / ide-backend

ide-backend drives the GHC API to build, query, and run your code
120 stars 17 forks source link

runStmt gets corrupted by async exceptions #219

Closed snoyberg closed 10 years ago

snoyberg commented 10 years ago

In the example below, I call runStmt twice. The first call is interrupted by an async exception due to the too short timeout. The second call then reliably throws that same exception.

{-# LANGUAGE OverloadedStrings #-}
import IdeSession
import Data.Monoid ((<>))
import System.Timeout (timeout)

main :: IO ()
main = do
    sess <- initSession defaultSessionInitParams defaultSessionConfig
    updateSession sess
        (updateSourceFile "Main.hs" "main = return ()" <> updateCodeGeneration True)
        print
    getSourceErrors sess >>= print

    _ <- timeout 1 $ runStmt sess "Main" "main"

    ra <- runStmt sess "Main" "main"
    let loop = do
            putStrLn "Calling runWait"
            x <- runWait ra
            putStrLn $ "Fnished runWait: " ++ show x
            case x of
                Left _ -> loop
                Right _ -> return ()
    loop

I discovered this since our deadlock workaround code includes a timeout call, which in fact triggers this problem.

edsko commented 10 years ago

I have pushed a change to experimental which addresses this. I am closing this issue for now, although the fix might not be optimal (see commit message).

edsko commented 10 years ago

I thought this was fixed but it still fails occasionally.

Mikolaj commented 10 years ago

I've tested the new version both under 7.4 and 7.8 and it works consistently this time.

snoyberg commented 10 years ago

Looks right to me. I've reinstated our timeout call around runStmt, and have not seen any issues. Thanks guys!

edsko commented 10 years ago

@snoyberg Note that runStmt should be treated as a resource allocation function and you therefore probably want to bracket it. As part of #231 I fixed it so that it will deallocate the child process if it gets interrupted, but once it leaves the scope of runStmt you need to make sure that you don't leak the runActions (with forceCancel or interrupt serving as deallocation function).

snoyberg commented 10 years ago

Thanks for the heads-up @edsko, I've created an issue to make sure I check the code for this: https://github.com/fpco/fpco/issues/3865