[GHC] #2233: Overhaul System.Process

GHC trac at galois.com
Fri May 23 10:26:12 EDT 2008


#2233: Overhaul System.Process
-------------------------------+--------------------------------------------
 Reporter:  simonmar           |          Owner:         
     Type:  proposal           |         Status:  new    
 Priority:  normal             |      Milestone:  Not GHC
Component:  libraries/process  |        Version:  6.8.2  
 Severity:  normal             |     Resolution:         
 Keywords:                     |     Difficulty:  Unknown
 Testcase:                     |   Architecture:  Unknown
       Os:  Unknown            |  
-------------------------------+--------------------------------------------
Comment (by duncan):

 Further to the changes already made we discussed some ideas on #ghc today:

 Deprecate:
  * `runCommand`
  * `runProcess`
  * `runInteractiveCommand`
  * `runInteractiveCommand`

 The rationale is that these are all more limited than the new
 `createProcess` and yet none of them are really convenient. It's better to
 have fewer variations if they can all be expressed easily using
 `createProcess`. It makes the API much simpler.

 Also we'd not add `system` or `rawSystem` to `System.Process`.

 That would leave just:

  * `createProcess`
  * `readProcess`
  * `readProcessWithExitCode`

 Then add the following:

  * `callProcess :: FilePath -> [String] -> IO ()`
  * `callCommand :: String -> IO ()`

 These would be synchronous like the current `system` and `rawSystem`. The
 difference is they would throw `IOError`s on failure rather than returning
 the `ExitCode` which is so easily ignored.

 These are of course only convenience functions. If someone wants the exit
 code it should be easy to do it via `createProcess` and `waitForProcess`.
 We need to make sure that is indeed the case.

 We'd also add async versions of the above:

  * `spawnProcess :: FilePath -> [String] -> IO ProcessHandle`
  * `spawnCommand :: String -> IO ProcessHandle`

 that do not wait for the process to finish and return the ProcessHandle.
 Again these should be easy instances of `createProcess`. The docs should
 probably say as much so it's clear how to make minor variations.

 We also discussed how it should be safe to GC the `ProcessHandle` and not
 end up with zombie processes on unix systems. On Windows it's actually
 easy because you can close the process handle which means you don't get
 the exit status of the process. On unix we have to collect the exit status
 of every child process (actually you can ignore all of them, but you
 cannot ignore them selectively).

 The point is that with a convenient `spawnProcess` it's tempting to ignore
 the `ProcessHandle` result and never bother calling `waitForProcess` on
 it. We do want to support that. At the moment doing that would leave
 zombie processes.

 We discussed a mechanism to allow GC'ing `ProcessHandle`s that does not
 leave zombies. It'd probably involve keeping a `Map PID (MVar ExitCode)`
 and embedding a `MVar ExitCode` in the `ProcessHandle`. Then when we get
 notified that a child process terminated we would store the exit status in
 the `MVar`. Then `waitForProcess` would just wait on that `MVar ExitCode`.

 The one thing we have left that we cannot express with `createProcess` is
 the behavior with respect to `^C` handling. For some processes we want to
 delegate `^C` handling to that child process (eg imagine calling `ghci`).
 For others we want to handle `^C` 'normally'. For details see #2301.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2233#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the Glasgow-haskell-bugs mailing list