views:

1352

answers:

5

After opening a pipe to a process with popen, is there a way to kill the thread that is started? Using pclose is not what I want because that will wait for the thread to finish, but I need to kill it.

A: 

The obvious way is system("pkill process_name");

Clearly this is problematic if you have more than one instance of the process running.

Andrew Grant
This does the case where multiple instances are running and one needs to target a precise instance.
jldupont
+3  A: 

popen does not actually start a thread, but rather forks a process. As I look at the definition, it doesn't look like there is an easy way to get PID of that process and kill it. There might be difficult ways like examining process tree, but i guess you'd be better off with using pipe, fork and exec functions to mimic behaviour of popen. Then you can use PID you get from fork() to kill the child process.

che
+6  A: 

Don't use popen(), and write your own wrapper that does what you'd like.

It's fairly straightforward to fork(), and then replace stdin & stdout by using dup2(), and then calling exec() on your child.

That way, your parent will have the exact child PID, and you can use kill() on that.

Google search for "popen2() implementation" for some sample code on how to implement what popen() is doing. It's only a dozen or so lines long. Taken from dzone.com we can see an example that looks like this:

#define READ 0
#define WRITE 1

pid_t
popen2(const char *command, int *infp, int *outfp)
{
    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return -1;

    pid = fork();

    if (pid < 0)
        return pid;
    else if (pid == 0)
    {
        close(p_stdin[WRITE]);
        dup2(p_stdin[READ], READ);
        close(p_stdout[READ]);
        dup2(p_stdout[WRITE], WRITE);

        execl("/bin/sh", "sh", "-c", command, NULL);
        perror("execl");
        exit(1);
    }

    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

    return pid;
}

NB: Seems like popen2() is what you want, but my distribution doesn't seem to come with this method.

slacy
+2  A: 

Actually if the process is doing I/O (which it should be, otherwise why popen instead of system(3)?), then pclose should whack it with a SIGPIPE the next time it tries to read or write, and it should fall over nicely :-)

Norman Ramsey
A: 

I did something similar in python, where you could kill a subprocess and any subprocesses forked for that. It's similar to slacy's solution actually. http://www.pixelbeat.org/libs/subProcess.py

pixelbeat