szmoore
szmoore

Reputation: 944

How do I terminate backgrounded ssh instances

I have written C program that uses fork(2) and execl(3) to run ssh for port forwarding purposes. The ssh's are run in the background the -f option.

When the C program exits, I want it to send SIGTERM to the ssh instances it spawned.

I have tried

// creating the ssh process
ssh_pid = fork();
if (ssh_pid == 0)
    execl("/usr/bin/ssh", "/usr/bin/ssh", "-f", other options, NULL)

// ...

printf("Killing %d\n", ssh_pid); // <--- output the PID
kill(ssh_pid, 15);
sleep(1); // give it a chance to exit properly
if (kill(ssh_pid, 0) == 0)
    kill(ssh_pid, 9); // the "shotgun" approach

However, this doesn't work (even with the SIGKILL).

If I run ps before the program exits

ps aux | grep ssh | grep -v sshd | grep -v grep

I see something like this:

user      27825  0.2  0.0      0     0 pts/0    Z+   18:23   0:00 [ssh] <defunct>
user      27834  0.0  0.0  41452  1176 ?        Ss   18:23   0:00 /usr/bin/ssh -f [other options]

When the program prints the PID it is killing, I see this:

Killing 27825

Subsequently repeating the ps gives me:

user      27834  0.0  0.0  41452  1176 ?        Ss   18:23   0:00 /usr/bin/ssh -f [other options]

It seems that the original ssh has forked itself in order to become a background process.

So I changed my call to kill(2) to attempt to kill all processes spawned by the original ssh:

kill(-ssh_pid, 15);

But this appears to have no effect. I suspect it is because the original ssh is no longer the parent of the backgrounded ssh.

So, how do I safely kill the backgrounded ssh? Is it even possible?

Upvotes: 2

Views: 586

Answers (1)

szmoore
szmoore

Reputation: 944

The solution I have just found is not to use the -f option at all, and background the ssh myself.

ssh_pid = fork();
if (ssh_pid == 0)
{
    freopen("/dev/null", "r", stdin);
    freopen("/dev/null", "w", stdout);
    freopen("/dev/null", "w", stderr);
    execl("/usr/bin/ssh", "/usr/bin/ssh", other options, NULL);
}

Because when ssh gets the -f option it creates a child, and signals sent to the parent won't get passed to the child.

Upvotes: 1

Related Questions