tags:

views:

265

answers:

3

I'm executing a shell pipeline from a java program - it'll be something like

ProcessBuilder builder = new ProcessBuilder(
                         "sh", "-c", "program1 | program2 | program3");
builder.start();

In some cases this unit might need to be terminated. However

process.destroy();

Will only destroy the "sh" command. The commands in the pipline will be orphaned and adopted by the init process.

Is there any way to easily terminate all these child processes - or execute a pipeline like the above in a way that makes it easier to terminate them . Altering progam 1/2/3 can't be done. Portability beyond linux is not a issue.

A: 

Instead of running the pipeline in the shell, build the pipeline in java.

You'll need three process builders then (one for program1, one for program2, and ... one for program3 :D), and some threads to transfer the output from each process' output stream to the input stream of the next process.

This way you get j.l.Process instances for each of the childs, and can call destroy() on those.

ankon
While a way, it'd be insanly ineffective as I'd have to emulate the pipes in java instead of a direct pipe between the programs. These programs transfer quite a few gigabytes of data to the next one.
Anonym
I'd actually be interested in measurements for that ... it is true that you need to pull the data from the streams manually, but I don't really think that this will produce 'insane ineffectivity'. Try it :)
ankon
+1  A: 

There's two ways I can think to do this:

  1. You could run a pkill program1 program2 program3

  2. You could write a intermediate program which launches the whole bash command line, this intermediate program would install a signal handler which kills it's own children when it gets a STOP signal.

Benj
Obviously the intermediate program would have to pass the in/out/err streams straight through.
Benj
A: 

Create a wrapper program in C that (a) launches the rest of the pipe, and (b) handles some signals by killing all the participants in the pipe before calling exit(2) itself.

bmargulies