how to terminate a (Posix) process and all its subprocesses?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

how to terminate a (Posix) process and all its subprocesses?

Johannes Waldmann-2
Dear Cafe,

I am using
https://hackage.haskell.org/package/process-1.6.4.0/docs/System-Process.html#v:readProcess
to start an external command, and wait for its completion.

Now I would like to time-out this after a while.
I can use
https://hackage.haskell.org/package/base-4.11.1.0/docs/System-Timeout.html
and this works in simple cases -

but not in case the external command has spawned child processes.
(cleanupProcess sends SIGTERM but only to the process at the top of
the tree ?)

I guess I need to use
https://hackage.haskell.org/package/unix-2.7.2.2/docs/System-Posix-Process.html
but that seems rather low-level - and I don't see how I would
get the ProcessID of the process started by  readProcess,
so I'd also have to re-do that.

Is there an abstraction/library that would help here?

Thanks - J.W.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how to terminate a (Posix) process and all its subprocesses?

Viktor Dukhovni


> On Jul 24, 2018, at 9:42 AM, Johannes Waldmann <[hidden email]> wrote:
>
> Now I would like to time-out this after a while.
> I can use
> https://hackage.haskell.org/package/base-4.11.1.0/docs/System-Timeout.html
> and this works in simple cases -
>
> but not in case the external command has spawned child processes.
> (cleanupProcess sends SIGTERM but only to the process at the top of
> the tree ?)

You could start a wrapper process that starts the real process,
the wrapper process would kill the process group it spawned.

        wrapper command [args ...]

would run command as a child in its own process group and propagates
termination signals (SIGHUP, SIGINT, SIGTERM) to the child process.

There are likely multiple such wrappers available.  I don't have
a particular one to recommend.

--
        Viktor.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how to terminate a (Posix) process and all its subprocesses?

Levent Erkok
In reply to this post by Johannes Waldmann-2
Hi Johannes:

I had a similar question a few years back using the async library and in particular the 'race' function. I got a nice answer on StackOverflow:


I think you can use the ideas in there. Bottom line: You can use a combination of 'onException' and 'terminateProcess' and let your spawned processes clean-up after themselves properly.

Cheers,

-Levent.

On Tue, Jul 24, 2018 at 6:42 AM, Johannes Waldmann <[hidden email]> wrote:
Dear Cafe,

I am using
https://hackage.haskell.org/package/process-1.6.4.0/docs/System-Process.html#v:readProcess
to start an external command, and wait for its completion.

Now I would like to time-out this after a while.
I can use
https://hackage.haskell.org/package/base-4.11.1.0/docs/System-Timeout.html
and this works in simple cases -

but not in case the external command has spawned child processes.
(cleanupProcess sends SIGTERM but only to the process at the top of
the tree ?)

I guess I need to use
https://hackage.haskell.org/package/unix-2.7.2.2/docs/System-Posix-Process.html
but that seems rather low-level - and I don't see how I would
get the ProcessID of the process started by  readProcess,
so I'd also have to re-do that.

Is there an abstraction/library that would help here?

Thanks - J.W.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how to terminate a (Posix) process and all its subprocesses?

Brandon Allbery
In reply to this post by Johannes Waldmann-2
The trick here is to set the option that creates a process group (System.Process's config record has a field for this), then extract the process id of the parent and negate it to get a process group ID. A signal sent to that will go to the entire process group.

You can do this with System.Process as opposed to System.Posix.Process, but you need to go digging into internals to get the process ID IIRC.

On Tue, Jul 24, 2018 at 9:42 AM Johannes Waldmann <[hidden email]> wrote:
Dear Cafe,

I am using
https://hackage.haskell.org/package/process-1.6.4.0/docs/System-Process.html#v:readProcess
to start an external command, and wait for its completion.

Now I would like to time-out this after a while.
I can use
https://hackage.haskell.org/package/base-4.11.1.0/docs/System-Timeout.html
and this works in simple cases -

but not in case the external command has spawned child processes.
(cleanupProcess sends SIGTERM but only to the process at the top of
the tree ?)

I guess I need to use
https://hackage.haskell.org/package/unix-2.7.2.2/docs/System-Posix-Process.html
but that seems rather low-level - and I don't see how I would
get the ProcessID of the process started by  readProcess,
so I'd also have to re-do that.

Is there an abstraction/library that would help here?

Thanks - J.W.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.


--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how to terminate a (Posix) process and all its subprocesses?

Johannes Waldmann-2
Hi Brandon, hi Levent,

> The trick here is to set the option that creates a process group

Ah yes!  interruptProcessGroupOf  seems to work here. Thanks very much.

My code:
https://gitlab.imn.htwk-leipzig.de/waldmann/pure-matchbox/blob/master/random-termination.hs#L141
but (apart from its general hackiness) I think it does not work right
when I thread-kill this from within my own program.
Which I don't, at the moment, but certainly will, sometime later.

- J.W.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how to terminate a (Posix) process and all its subprocesses?

Bardur Arantsson-2
In reply to this post by Johannes Waldmann-2
On 2018-07-24 15:42, Johannes Waldmann wrote:
> Dear Cafe,
>
> I am using
> https://hackage.haskell.org/package/process-1.6.4.0/docs/System-Process.html#v:readProcess
> to start an external command, and wait for its completion.
>

If the process is hostile (e.g. fork bomb + countermeasures), then the
*only* realiable way to do this is to use cgroups.

Obviously, this applies to Linux only. I'm not sure there's actually any
truly POSIX way to reliably kill hostile sub-processes. I don't think
so. (The progress group thing doesn't work if the process is hostile.
It'll work fine otherwise.)

Regards,

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how to terminate a (Posix) process and all its subprocesses?

David Feuer
If the process is not thought to be hostile, I imagine it's best to first try signaling only the parent, and only signal the group if necessary. Otherwise, you may prevent it from cleaning up after itself properly. Dunno how to wait for the group to die.

On Tue, Jul 24, 2018, 3:21 PM Bardur Arantsson <[hidden email]> wrote:
On 2018-07-24 15:42, Johannes Waldmann wrote:
> Dear Cafe,
>
> I am using
> https://hackage.haskell.org/package/process-1.6.4.0/docs/System-Process.html#v:readProcess
> to start an external command, and wait for its completion.
>

If the process is hostile (e.g. fork bomb + countermeasures), then the
*only* realiable way to do this is to use cgroups.

Obviously, this applies to Linux only. I'm not sure there's actually any
truly POSIX way to reliably kill hostile sub-processes. I don't think
so. (The progress group thing doesn't work if the process is hostile.
It'll work fine otherwise.)

Regards,

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how to terminate a (Posix) process and all its subprocesses?

Brandon Allbery
https://downloads.haskell.org/~ghc/latest/docs/html/libraries/unix-2.7.2.2/System-Posix-Process.html#v:getGroupProcessStatus (at a lower level, this is waitpid() with a negative process ID, expressing the process group whose leader has abs(process ID)).

And yes, if a process puts itself into its own process group, it will be immune to control in this fashion. You can do a bit more with sessions instead of pgroups, but then a process could put itself into its own session. cgroups are pretty much the only way to avoid this… if and only if you prevent processes in a given cgroup from creating new cgroups. It's something of an infinite regression.

As for cleanup, the convention is you use signal 15 (SIGTERM) to indicate "clean up and exit". If after a reasonable amount of time (typically some number of seconds) something is still running, you repeat with signal 9 (SIGKILL, which can't be blocked or masked). SIGTERM is usually sent to the entire process group, as individual processes may have their own distinct cleanup needs.

On Tue, Jul 24, 2018 at 3:26 PM David Feuer <[hidden email]> wrote:
If the process is not thought to be hostile, I imagine it's best to first try signaling only the parent, and only signal the group if necessary. Otherwise, you may prevent it from cleaning up after itself properly. Dunno how to wait for the group to die.

On Tue, Jul 24, 2018, 3:21 PM Bardur Arantsson <[hidden email]> wrote:
On 2018-07-24 15:42, Johannes Waldmann wrote:
> Dear Cafe,
>
> I am using
> https://hackage.haskell.org/package/process-1.6.4.0/docs/System-Process.html#v:readProcess
> to start an external command, and wait for its completion.
>

If the process is hostile (e.g. fork bomb + countermeasures), then the
*only* realiable way to do this is to use cgroups.

Obviously, this applies to Linux only. I'm not sure there's actually any
truly POSIX way to reliably kill hostile sub-processes. I don't think
so. (The progress group thing doesn't work if the process is hostile.
It'll work fine otherwise.)

Regards,

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.


--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.