You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm concerned that withCreateProcess may fail to clean up if an async exception is received at just the wrong time. I do not have a test case to prove it, but my reasoning follows.
See Control.Exception's discussion of "Interruptible operations". The masking of async exceptions by bracket when cleanupProcess is running only prevents non-interruptable operations from receiving an async exception. So if any operation in cleanupProcess turns out to be interruptable, an async exception received during that operation will prevent the rest of it from running.
Looking at the operations that get run, there's a takeMVar, but I think the MVar is always full, so it's not interruptable. Then it closes the IO handles, and as far as I can see, hClose is interruptable, or at least is not documented not to be.
So, an async exception received just as hClose is run will terminate the thread, and waitForProcess will never wait on the process. (IO handles could also potentially be left open, although generally GC will auto-close them when they go out of scope.) It's probably a rather narrow race condition.
My analysis could be wrong, but eh, if I've been staring at this code for an hour and I don't know if it it's correct, it seems like it would be a good idea to make sure this doesn't happen by using uninterruptibleMask somewhere?
(The closest I have come to a test case is modifying cleanupProcess to add threadDelay 100, and then it's easy to time the async exception to interrupt it, leaving the process running. But of course it might be threadDelay itself that's the interruptable operation in that case.)
The text was updated successfully, but these errors were encountered:
An alternative to uninterruptibleMask would be to work off a worker thread to do all the closing etc, and wait on it before returning. That insulates it from receiving async exceptions, and won't prevent the program from being interrupted by ctrl-c while it's running.
This topic is an ongoing debate in the Haskell community. I agree with uninterruptible being the right behavior for cleanups, and wish bracket worked that way. I'm not sure if it's a good idea to change an existing function in a core library with a difficult-to-notice semantics change, however.
I'm concerned that withCreateProcess may fail to clean up if an async exception is received at just the wrong time. I do not have a test case to prove it, but my reasoning follows.
See Control.Exception's discussion of "Interruptible operations". The masking of async exceptions by bracket when cleanupProcess is running only prevents non-interruptable operations from receiving an async exception. So if any operation in cleanupProcess turns out to be interruptable, an async exception received during that operation will prevent the rest of it from running.
Looking at the operations that get run, there's a takeMVar, but I think the MVar is always full, so it's not interruptable. Then it closes the IO handles, and as far as I can see, hClose is interruptable, or at least is not documented not to be.
So, an async exception received just as hClose is run will terminate the thread, and waitForProcess will never wait on the process. (IO handles could also potentially be left open, although generally GC will auto-close them when they go out of scope.) It's probably a rather narrow race condition.
My analysis could be wrong, but eh, if I've been staring at this code for an hour and I don't know if it it's correct, it seems like it would be a good idea to make sure this doesn't happen by using uninterruptibleMask somewhere?
(The closest I have come to a test case is modifying cleanupProcess to add threadDelay 100, and then it's easy to time the async exception to interrupt it, leaving the process running. But of course it might be threadDelay itself that's the interruptable operation in that case.)
The text was updated successfully, but these errors were encountered: