Opened 8 years ago

Closed 18 months ago

Last modified 3 months ago

#5611 closed bug (fixed)

Asynchronous exception discarded after safe FFI call

Reported by: joeyadams Owned by:
Priority: normal Milestone: 8.6.1
Component: Runtime System Version: 7.0.3
Keywords: FFI, exception, Exceptions Cc: ezyang
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

Note: This bug appears to be fixed already, as it does not appear with GHC 7.2.1 . I'm submitting a bug report anyway, to document its presence.

The bug is: when an asynchronous exception is thrown to a thread making a (safe) foreign call, the thread throwing the exception blocks like it should, but then the exception isn't actually delivered. For example:

{-# LANGUAGE ForeignFunctionInterface #-}

import Control.Concurrent
import Foreign.C
import System.IO

foreign import ccall safe "unistd.h sleep"
    sleep :: CUInt -> IO CUInt

main :: IO ()
main = do
    hSetBuffering stdout LineBuffering

    tid <- forkIO $ do
        putStrLn "child: Sleeping"
        _ <- sleep 1

        -- The following lines should not happen after the killThread from the
        -- parent thread completes.  However, they do...
        putStrLn "child: Done sleeping"
        threadDelay 1000000
        putStrLn "child: Done waiting"

    threadDelay 100000
    putStrLn $ "parent: Throwing exception to thread " ++ show tid
    throwTo tid $ userError "Exception delivered successfully"
    putStrLn "parent: Done throwing exception"

    threadDelay 2000000

When the bug is present, the program prints:

child: Sleeping
parent: Throwing exception to thread ThreadId 4
child: Done sleeping
parent: Done throwing exception
child: Done waiting

"child: Done waiting" should not be printed after completion of the throwTo, and the exception message should appear. On GHC 7.2.1, the program prints:

child: Sleeping
parent: Throwing exception to thread ThreadId 4
parent: Done throwing exception
ffi-sleep: user error (Exception delivered successfully)

This bug has been reproduced in GHC 7.0.3, on both Linux and Windows. It has also been reproduced on GHC 7.0.4.

Change History (8)

comment:1 Changed 8 years ago by simonmar

Owner: set to simonmar

Thanks for the report.

This appears to have been fixed by commit 539d3adec64f51a3fb13bb65b7a494d7eded01a0, though the log message doesn't give any clues about whether it was diagnosed or not. I'll add your program as a test case.

comment:2 Changed 8 years ago by simonmar

Milestone: 7.2.1
Resolution: fixed
Status: newclosed

resolving as fixed in 7.2.1

comment:3 Changed 4 years ago by thomie

Cc: ezyang added
Owner: simonmar deleted
Resolution: fixed
Status: closednew

This test just failed on me, but just once, not repeatedly.

It printed child: Done waiting intead of user error (Exception delivered successfully).

I was validating an unrelated patch on Phabricator: https://phabricator.haskell.org/harbormaster/build/5908/ (Phab:D1209)

CC ezyang, since he worked on this problem before, according to comment:1.

comment:4 Changed 3 years ago by dfeuer

Milestone: 7.2.18.4.1

comment:5 Changed 3 years ago by dfeuer

Keywords: Exceptions added

comment:6 Changed 20 months ago by bgamari

Milestone: 8.4.18.6.1

This ticket won't be resolved in 8.4; remilestoning for 8.6. Do holler if you are affected by this or would otherwise like to work on it.

comment:7 Changed 18 months ago by bgamari

Resolution: fixed
Status: newclosed

I've not seen this fail on CI in the years I've been looking at results. I'm going to call this resolved.

comment:8 Changed 3 months ago by Ben Gamari <ben@…>

In 58e84b30/ghc:

testsuite: Use safe FFI call in T5611

The original issue, #5611, was concerned with safe calls. However, the
test inexplicably used an unsafe call. Fix this.
Note: See TracTickets for help on using tickets.