Ticket #4162 (new bug)

Opened 3 years ago

Last modified 8 months ago

GHC API messes up signal handlers

Reported by: jcpetruzza Owned by:
Priority: low Milestone: 7.6.2
Component: GHC API Version: 6.12.3
Keywords: Cc: chowells79@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty:
Test Case: Blocked By:
Blocking: Related Tickets:

Description

A side-effect of using the runGhc function is that some signal handlers are modified and not restored afterwards (see function initGhcMonad). In particular, the handler for SIGINT installed by ghc throws an exception to a thread stored in a global variable, which initially corresponds to the thread from which runGhc was run.

This is a particularly problematic for programs that wish to run ghc "in the background" on its own thread. For example, consider this code:

import qualified GHC
import qualified MonadUtils as GHC
import qualified GHC.Paths as GHC

import Control.Concurrent ( forkIO, threadDelay )

main = do
   putStrLn "waiting for 5 seconds..."
   threadDelay $ 5 * 1000 * 1000
   putStrLn "starting..."
   forkIO $ GHC.runGhc (Just GHC.libdir) (GHC.liftIO $ putStrLn "hello")
   putStrLn "waiting for 10 seconds"
   threadDelay $ 10 * 1000 * 1000
   putStrLn "exiting after final wait"

One can interrupt this program with Ctrl-C during the first five seconds of execution only.

It is not clear to me how one can safely workaround this problem. For instance, one could manually restore the program's original handlers at the beginning of execution, that is, transform:

runGhc action

into something like this:

runGhc $ (liftIO restoreProgramHandlers >> action)

but I don't know if this is safe (i.e., what happens if ghc is run without its own handlers installed).

Change History

follow-up: ↓ 3   Changed 3 years ago by carlhowells

If anyone with knowledge of the GHC api could chime in, I'd greatly appreciate it. I'm waiting on an update to the hint package, which is waiting on a response to this.

This comes down to two things, fundamentally:

1) It's a bug that the GHC api changes signal handlers, and doesn't change them back when it's finished. The GHC api probably shouldn't even touch signal handlers. The handler it's installing is part of GHCi, not the GHC api. Hence I believe GHCi code should be installing it, not the GHC api.

2) Given the current behavior, is it a safe workaround to restore the previous signal handlers inside the action runGhc is performing, or should restoring them be delayed until runGhc returns?

An answer to the latter is what's required for forward progress on hint. The former is less urgent, but should be considered a bug to some degree in the GHC api.

  Changed 3 years ago by carlhowells

  • cc chowells79@… added

in reply to: ↑ 1   Changed 3 years ago by simonmar

  • milestone set to 6.14.1

Replying to carlhowells:

1) It's a bug that the GHC api changes signal handlers, and doesn't change them back when it's finished. The GHC api probably shouldn't even touch signal handlers. The handler it's installing is part of GHCi, not the GHC api. Hence I believe GHCi code should be installing it, not the GHC api.

I sympathise with that view. However, it's not entirely straightforward to change, because when GHC executes an expression interactively, it starts a new thread, so Ctrl-C exceptions have to be directed to the correct thread. There would probably need to be some callback mechanism from the GHC API back to the client to inform the client that interrupts need to be directed to a new thread.

I agree we should do this, so let's leave the ticket open.

2) Given the current behavior, is it a safe workaround to restore the previous signal handlers inside the action runGhc is performing, or should restoring them be delayed until runGhc returns?

restoring the signal handler should be fine. Note we also catch SIGHUP, SIGTERM, and SIGQUIT, to ensure that GHC cleans up temporary files if any of these are caught.

An answer to the latter is what's required for forward progress on hint. The former is less urgent, but should be considered a bug to some degree in the GHC api.

  Changed 2 years ago by igloo

  • milestone changed from 7.0.1 to 7.0.2

  Changed 2 years ago by igloo

  • milestone changed from 7.0.2 to 7.2.1

  Changed 20 months ago by igloo

  • milestone changed from 7.2.1 to 7.4.1

  Changed 16 months ago by igloo

  • priority changed from normal to low
  • milestone changed from 7.4.1 to 7.6.1

  Changed 8 months ago by igloo

  • milestone changed from 7.6.1 to 7.6.2
Note: See TracTickets for help on using tickets.