How to terminate the process group of a process created with createProcess?

Hello, (on unix) creating a process A which spawns itself a subprocess B and terminating process A before it finishes leaves process B as a process on its own. This is because "terminateProcess" sends the sigterm signal to the process only and not to its process group. Is there a way to terminate the process group of process A? Or alternatively is there a way to get he Posix ProcessId of process A? The following is a minimal example. The process "sleep 60" survives the termination of both "sleep" and of the main program. <code> module Main where import Control.Concurrent import System.Process main = do h@(_, _, _, hProc) <- createProcess (proc "time" ["sleep", "60"]) threadDelay $ 5 * 1000000 terminateProcess hProc waitForProcess hProc </code> Kind regards, André

On Wed, Jan 11, 2012 at 16:26, André Scholz
(on unix) creating a process A which spawns itself a subprocess B and terminating process A before it finishes leaves process B as a process on its own. This is because "terminateProcess" sends the sigterm signal to the process only and not to its process group.
terminateProcess passes on the semantics of kill(2); on SVID-compliant (and I think POSIX.1-compliant) systems, the negative of the process group leader's process ID is used to signal the process group. Note that you may need to arrange for your initial child process to invoke setpgrp() to insure that the parent program is not part of the process group. However I'm unclear as to the situation you are encountering, as your example does not appear to be spawning an intermediate process. -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

Quoth Brandon Allbery
terminateProcess passes on the semantics of kill(2); on SVID-compliant (and I think POSIX.1-compliant) systems, the negative of the process group leader's process ID is used to signal the process group. Note that you may need to arrange for your initial child process to invoke setpgrp() to insure that the parent program is not part of the process group.
... and that stuff can be found in System.Posix.Process. Support for POSIX killpg can be found in System.Posix.Signals, by the way in case you think that would make your intention more transparent.
However I'm unclear as to the situation you are encountering, as your example does not appear to be spawning an intermediate process.
I missed that at first myself -- he actually invokes "time sleep 60". Donn

On 11.01.2012 at 23:08 Donn Cave wrote:
Quoth Brandon Allbery
, ... terminateProcess passes on the semantics of kill(2); on SVID-compliant (and I think POSIX.1-compliant) systems, the negative of the process group leader's process ID is used to signal the process group. Note that you may need to arrange for your initial child process to invoke setpgrp() to insure that the parent program is not part of the process group.
... and that stuff can be found in System.Posix.Process. Support for POSIX killpg can be found in System.Posix.Signals, by the way in case you think that would make your intention more transparent.
I tried: import System.Posix.Process import System.Posix.Signals import System.Process import System.Process.Internals terminateProcessGroup :: ProcessHandle -> IO () terminateProcessGroup ph = do let (ProcessHandle pmvar) = ph ph_ <- readMVar pmvar case ph_ of OpenHandle pid -> do -- pid is a POSIX pid gid <- createProcessGroup pid signalProcessGroup 15 pid otherwise -> error "Somethings wrong." but i get the error message: "createProcessGroup: permission denied" Is there a way around this permission problem? Kind regards, André

On Thu, Jan 12, 2012 at 06:56, André Scholz
gid <- createProcessGroup pid
but i get the error message: "createProcessGroup: permission denied"
It's only going to work on BSDish systems; on systems using the SVID/POSIX model, only the current process can be converted into a process group leader, and only if it isn't already one. I need to go look at the implementation of System.Process, though; the documentation strongly implies that (a) it already creates a process group, at least on UNIX (there's an additional step needed to do so on Windows?) and (b) terminateProcess is claimed to signal the process group, as is interruptProcessGroupOf (the documentation is clearer here). [[Having looked: the documentation for terminateProcess is incorrect and should not mention process groups, but the documentation for interruptProcessGroupOf is correct. Maybe that function will work for you?]] In any case, I would not mix System.Process and System.Posix.Process. I'd probably use the latter, but that's because it's closer to what I'm used to as a Unix/SVID/POSIX programmer. -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

Quoth Brandon Allbery
On Thu, Jan 12, 2012 at 06:56, André Scholz
wrote: gid <- createProcessGroup pid
but i get the error message: "createProcessGroup: permission denied"
the documentation for terminateProcess is incorrect and should not mention process groups
Right - and terminateProcess should _not_ be fixed to work like the documentation says! I think it's just a point of confusion over how the shell works - in fact, process groups are normally created by the shell, but only when it's serving as the top level interactive shell.
In any case, I would not mix System.Process and System.Posix.Process. I'd probably use the latter, but that's because it's closer to what I'm used to as a Unix/SVID/POSIX programmer.
Same here, and in any case I don't expect there's any way to do this with System.Process, i.e., portably on non-UNIX platforms. In the System.Posix.Process variant, you get to use "fork" directly: spawn :: String -> [String] -> IO ProcessID spawn exe cmd = forkProcess $ executeFile exe False cmd Nothing To set the process group, spawnpg exe cmd = forkProcess $ do getProcessID >>= joinProcessGroup -- equivalent to setpgrp() executeFile exe False cmd Nothing ... to terminate the process group, signalProcessGroup sigTERM pid ... and wait for the spawned process getProcessStatus True False pid When you're running Haskell in the child fork like this, you could run afoul of runtime thread support, and depending on your situation it might make sense to move the fork/setpgrp/exec out into a C function to avoid that. Donn

Hello, On 12.01.2012 at 17:00 Brandon Allbery wrote:
I need to go look at the implementation of System.Process, though; the documentation strongly implies that (a) it already creates a process group,
System.Process-1.1.0.0 introduces the new field "create_group :: Bool" in the datatype CreateProcess, which ensures that the process (and its children) is spawned in an new process group.
but the documentation for interruptProcessGroupOf is correct. Maybe that function will work for you?
This function is also in System.Process-1.1.0.0 and does indeed, what i want to do!
In any case, I would not mix System.Process and System.Posix.Process. I'd probably use the latter, but that's because it's closer to what I'm used to as a Unix/SVID/POSIX programmer.
I thought so, but the means justified the ends (for me , in this case). But now i don't need System.Posix.Process at all, since all i need is provided by the new System.Process-1.1.0.0. Thank you for pointing out the function "interruptProcessGroupOf" which lead me to this new version of System.Process. Kind regards, André
participants (3)
-
André Scholz
-
Brandon Allbery
-
Donn Cave