10

I'm opening a long-running process with popen(). For debugging, I'd like to terminate the process before it has completed. Calling pclose() just blocks until the child completes.

How can I kill the process? I don't see any easy way to get the pid out of the resource that popen() returns so that I can send it a signal.

I suppose I could do something kludgey and try to fudge the pid into the output using some sort of command-line hackery...

Frank Farmer
  • 38,246
  • 12
  • 71
  • 89
  • This is not a real answer because it's for C and not PHP, but see this link for a suggestion: http://www.monkey.org/openbsd/archive/misc/0112/msg00360.html – Nate C-K Jan 19 '11 at 04:14

3 Answers3

8

Well, landed on a solution: I switched back to proc_open() instead of popen(). Then it's as simple as:

$s = proc_get_status($p);
posix_kill($s['pid'], SIGKILL);
proc_close($p);
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Frank Farmer
  • 38,246
  • 12
  • 71
  • 89
  • I was having the same problem with `proc_open()`, so I tried the simpler `popen()`, hoping that would help. I didn't realize, at the time, that *both* `pclose()` and `proc_close()` block until the child terminates. Once you realize that, then you have to kill the child. And to kill the child you need the pid, and that isn't cleanly available with `popen()`. `proc_open()` does everything `popen()` does, and then some. – Frank Farmer Jan 19 '11 at 04:20
  • please tick your own answer so that people know you've found the solution. – mauris Jan 19 '11 at 04:21
  • @thephpdeveloper SO gives me a "You can accept your own answer tomorrow" error, right now. – Frank Farmer Jan 19 '11 at 20:03
  • 2
    look at http://www.php.net/manual/en/function.proc-terminate.php#81353 because you need to kill all child process if any. – EGL 2-101 Oct 03 '11 at 21:49
0

Just send a kill (or abort) signal using kill function:

Elalfer
  • 5,312
  • 20
  • 25
  • 1
    The tricky part is doing a good job of figuring out which pid to kill :) Once you're sure you've got the right pid, then you can call php's `posix_kill()`. I suppose in retrospect, I could have grepped the list of child pids from ps, since it's easy to figure out my own pid. – Frank Farmer Jan 19 '11 at 04:16
0

You can find the pid, and checks that you're really its parent by doing:

// Find child processes according to current pid
$res = trim(exec('ps -eo pid,ppid |grep "'.getmypid().'" |head -n2 |tail -n1'));
if (preg_match('~^(\d+)\s+(\d+)$~', $res, $pid) !== 0 && (int) $pid[2] === getmypid())
{
    // I'm the parent PID, just send a KILL
    posix_kill((int) $pid[1], 9);
}

It's working quite well on a fast-cgi PHP server.

Yvan
  • 2,539
  • 26
  • 28