#2301: Proper handling of SIGINT/SIGQUIT
-------------------------------+--------------------------------------------
 Reporter:  duncan             |          Owner:         
     Type:  bug                |         Status:  new    
 Priority:  normal             |      Milestone:  6.10.1 
Component:  libraries/process  |        Version:  6.8.2  
 Severity:  normal             |     Resolution:         
 Keywords:                     |     Difficulty:  Unknown
 Testcase:                     |   Architecture:  Unknown
       Os:  Multiple           |  
-------------------------------+--------------------------------------------
Comment (by duncan):

 So the next part is how we handle `^C` when we are running foreground
 processes. I think the behaviour suggested in the above description is
 right but lets try to flesh it out a bit more and suggest how it could be
 implemented.

 Some terminology: technically all processes we launch are in the
 foreground. Putting a process into the background has to be done
 explicitly. However that does not means that logically we consider all
 processes to be in the foreground. We often launch processes and do not
 expect them to communicate with the user via the console or we may connect
 them via pipes and not let them use the console at all.

 So we only want to delegate`^C` handling to some processes. Delegating
 `^C` handling is a property of a process which we set when we launch it.

 When we get a `^C` there are two cases:
  * we are running one or more processes to which we consider we are
 delegating `^C` handling
  * we are running no such processes

 The second case is easy and is addressed by the patch above. We throw an
 exception to the main thread which will typically propagate and terminate
 the program.

 In the first case we do not want to throw any exception immediately.
 However when processes to which we were delegating `^C` handling terminate
 due to `^C` we should at that point throw an exception to the main thread.

 So how could we implement this?

 Delegated `^C` handling becomes another property of a process we launch.
 We keep a global count of the number of such processes we're running. We
 use that count to decide if we should throw an exception to the main
 thread when we receive `SIGINT` or not. We will also need to record in the
 map of launched processes if we were delegating `^C` handling or not. This
 means changing from a `Map PID (MVar ExitCode)` to a `Map PID (Bool, MVar
 ExitCode)`. When the `SIGCHILD` handler runs for a PID it will look it up
 in the map, if we were delegating ^C handling for that process and it
 terminated due to `^C` then it should throw an exception to the main
 thread, exactly as the `^C` handler would do when there were no delegated
 `^C` processes running. It should also set the `MVar ExitCode` since the
 main thread may well be ignoring `^C` exceptions and want to continue as
 normal.

 So in both cases, `^C` happens as an async exception in the main thread.
 The difference is whether it happens when the `^C` is first received or
 when a process to which we are delegating `^C` handling terminates due to
 `^C`.

 So the `CreateProcess` record will need an extra field to indicate if
 we're delegating `^C` handling. That will make it possible to implement
 the old `system` and `rawSystem` functions in terms of `createProcess`.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2301#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to