runGhc installs signal handlers (on both posix and windows) to
- redirect ^C to execStmt, which we just don't care about and we have a workaround in place (with a bit of a race condition)
- clean out temporary files
- terminate the external interpreter.
However it doesn't do a good job at accomplishing the above in a multi-threaded application with possibly many ghc sessions [1].
Issue #4162 on ghc's tracker is about how problematic these signal handlers are, but has been stalled for 15 years atm.
In our case the DAP library will killThread our debug session threads when destroyDebugSession is called, which will trigger the cleanup.
Ideally we would have a similar broadcasting mechanism that's triggered by sigTERM and other signals, combined with some way to wait for the cleanup to complete.
Maybe what we come up with could even fix #4162 upstream?
[1] For example a SIGTERM will be delivered (as a Signal 15 :: GhcException) to just one of the threads that have executed a runGhc and which might not even be running anymore. (There's a reference counting mechanism to uninstall the handlers, but it never updates the receiver thread id: the only way it will setup a new receiver is if a new runGhc/runGhcT call happens after all the previous ones have already terminated).
runGhcinstalls signal handlers (on both posix and windows) toHowever it doesn't do a good job at accomplishing the above in a multi-threaded application with possibly many ghc sessions [1].
Issue #4162 on ghc's tracker is about how problematic these signal handlers are, but has been stalled for 15 years atm.
In our case the DAP library will
killThreadour debug session threads whendestroyDebugSessionis called, which will trigger the cleanup.Ideally we would have a similar broadcasting mechanism that's triggered by sigTERM and other signals, combined with some way to wait for the cleanup to complete.
Maybe what we come up with could even fix #4162 upstream?
[1] For example a SIGTERM will be delivered (as a Signal 15 :: GhcException) to just one of the threads that have executed a
runGhcand which might not even be running anymore. (There's a reference counting mechanism to uninstall the handlers, but it never updates the receiver thread id: the only way it will setup a new receiver is if a newrunGhc/runGhcTcall happens after all the previous ones have already terminated).