[GHC] #9030: An async exception handler that blocks throwTo until handler finishes running

#9030: An async exception handler that blocks throwTo until handler finishes running ------------------------------------+------------------------------------- Reporter: jberryman | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Keywords: | Operating System: Unknown/Multiple Architecture: Unknown/Multiple | Type of failure: None/Unknown Difficulty: Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | ------------------------------------+------------------------------------- I'd like to be able to handle an async exception in thread `A` such that if another thread `B` calls `throwTo`, that call blocks until my handler in `A` has a chance to ''finish''. Currently `throwTo` only blocks until the exception is "received" (which I don't understand precisely). My application is a concurrent FIFO queue library, in which a blocked reader must perform a cleanup action on async exceptions, else the next write will be lost: {{{ testBlockedRecovery = do c <- newChan started <- newEmptyMVar rid <- forkIO (putMVar started () >> readChan c) takeMVar started >> threadDelay 1000 throwTo rid ThreadKilled -- we race the exception-handler in `readChan` here... writeChan c () -- If this write won, then the write was lost and we block indefinitely below: readChan c putStrLn "OK" }}} If in my library I could catch the exception in such a way that `throwTo` blocked until I could handle it, then the test above would pass and the behavior of my Chan would match the standard library. This might seem like a lame example, but I think this functionality would be very generally useful. It would let you recover to a state using an exception handler such that you can reason in terms of linearizability about the pre- and post- exception states; I assume that's sort of the thinking behind making `throwTo` synchronous in the first place. Thanks and please let me know if there's actually a way to do what I'm asking currently, or if any of that wasn't clear. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9030 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9030: An async exception handler that blocks throwTo until handler finishes running -------------------------------------+------------------------------------ Reporter: jberryman | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by ezyang): Why can't you pass an MVar in the thrown exception (which the throwing thread blocks on), which the handler writes to when it is done? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9030#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9030: An async exception handler that blocks throwTo until handler finishes running -------------------------------------+------------------------------------ Reporter: jberryman | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by jberryman): Sure, but the `throwTo` is something the users of my library are doing. Or maybe they're using the `async` lib which is doing the `throwTo ThreadKilled`. In this particular case I think the user will have a mental model of what should happen when a blocked reader thread is killed (which matches the behavior of standard `Chan`), and I'd rather just be able to implement that rather than document weird corner-cases or force users to use a particular function or `Exception` type (although thanks for that idea; I'll probably warm up to that as a workaround). Maybe users never in practice think or care much about what happens when they do a `throwTo` and I just have to worry about not leaving my data structure broken; I'm not really sure. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9030#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9030: An async exception handler that blocks throwTo until handler finishes running -------------------------------------+------------------------------------ Reporter: jberryman | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by ezyang): OK, I looked at your example more carefully, I think this alternate design is more appropriate: you should just mask exceptions before reading from the channel. (Now readChan never services an exception once it has successfully read from the MVar, it will finish processing before admitting the exception.) Mask is exactly about setting up the linearizability properly. This won't help if a blocking call inside the mask requires an exception handler to run, but it feels like this should be rare (i.e. you shouldn't hold onto resources if you're going to block). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9030#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9030: An async exception handler that blocks throwTo until handler finishes running -------------------------------------+------------------------------------ Reporter: jberryman | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by jberryman): I don't really follow you. I'm certainly already masking exceptions in my `readChan` to avoid leaving the structure in a broken state, but an exception can (and must be permitted to) be raised when `readChan` is blocking on an empty queue (blocking on an MVar internally). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9030#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9030: An async exception handler that blocks throwTo until handler finishes running -------------------------------------+------------------------------------ Reporter: jberryman | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by ezyang): Oh sorry, my mistake, readChan is using `modifyMVarMasked`, not `modifyMVar`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9030#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC