标准输出影响SIGKILL? [英] standard output impact SIGKILL?

查看:118
本文介绍了标准输出影响SIGKILL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个脚本来限制命令的执行时间.

I have a script to limit the execution time length of commands.

limit.php

<?php
declare(ticks = 1);

if ($argc<2) die("Wrong parameter\n");
$cmd = $argv[1];
$tl = isset($argv[2]) ? intval($argv[2]) : 3;

$pid = pcntl_fork();
if (-1 == $pid) {
    die('FORK_FAILED');
} elseif ($pid == 0) {
    exec($cmd);
    posix_kill(posix_getppid(), SIGALRM);
} else {
    pcntl_signal(SIGALRM, create_function('$signo',"die('EXECUTE_ENDED');"));
    sleep($tl);
    posix_kill($pid, SIGKILL);
    die("TIMEOUT_KILLED : $pid");
}

然后我用一些命令测试此脚本.

Then I test this script with some commands.

测试A

php limit.php "php -r 'while(1){sleep(1);echo PHP_OS;}'" 3

3秒后,我们可以发现进程已按预期终止.

After 3s, we can find the processes were killed as we expected.

测试B

删除输出代码,然后再次运行.

Remove the output code and run again.

php limit.php "php -r 'while(1){sleep(1);}'" 3

结果看起来不太好,由函数"exec"创建的进程没有像测试A那样被杀死.

Result looks not good, the process created by function "exec" was not killed like TEST A.

[alix@s4 tmp]$ ps aux | grep whil[e]
alix      4433  0.0  0.1 139644  6860 pts/0    S    10:32   0:00 php -r while(1){sleep(1);}

系统信息

[alix@s4 tmp]$ uname -a
Linux s4 2.6.18-308.1.1.el5 #1 SMP Wed Mar 7 04:16:51 EST 2012 x86_64 x86_64 x86_64 GNU/Linux
[alix@s4 tmp]$ php -v
PHP 5.3.9 (cli) (built: Feb 15 2012 11:54:46) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

为什么进程在TEST A中被杀死,而在TEST B中没有?输出是否会影响SIGKILL?

Why the processes killed in TEST A but not in TEST B? Does the output impact the SIGKILL?

有什么建议吗?

推荐答案

php -r 'while(1){sleep(1);echo PHP_OS;}(process C)和它的父级(process B)之间有一个PIPEposix_kill($pid, SIGKILL)发送KILL信号到process B,然后process B被终止,但是process C对信号一无所知,并继续运行,并在process C接收到SIGPIPE信号但不知道时将某些内容输出到broken pipe如何处理它以便退出.

There is a PIPE between php -r 'while(1){sleep(1);echo PHP_OS;} (process C) and it's parent (process B), posix_kill($pid, SIGKILL) sends KILL signal to process B, then process B is terminated, but process C doesn't know anything about the signal and continues to run and outputs something to the broken pipe, when process C receives the SIGPIPE signal but has no idea how to handle it so it exits.

您可以使用strace验证它(运行php limit.php "strace php -r 'while(1){sleep(1); echo PHP_OS;};'" 1),您将看到类似以下内容:

You can verify it with strace (run php limit.php "strace php -r 'while(1){sleep(1); echo PHP_OS;};'" 1), and you will see something like this:

14:43:49.254809 write(1, "Linux", 5)    = -1 EPIPE (Broken pipe)
14:43:49.254952 --- SIGPIPE (Broken pipe) @ 0 (0) ---
14:43:49.255110 close(2)                = 0
14:43:49.255212 close(1)                = 0
14:43:49.255307 close(0)                = 0
14:43:49.255402 munmap(0x7fb0762f2000, 4096) = 0
14:43:49.257781 munmap(0x7fb076342000, 1052672) = 0
14:43:49.258100 munmap(0x7fb076443000, 266240) = 0
14:43:49.258268 munmap(0x7fb0762f3000, 323584) = 0
14:43:49.258555 exit_group(0)           = ?

关于php -r 'while(1){sleep(1);},因为broken pipe的父项去世后没有发生,所以它继续按预期运行.

As to php -r 'while(1){sleep(1);}, because there is no broken pipe occurs after it's parent dies, so it continues to run as expected.

通常来说,您应该杀死整个进程组,但如果要杀死它的子进程,则不仅要杀死进程本身,还可以使用PHP杀死process B到其自己的进程组中,然后杀死整个进程组,这是您代码的差异:

Generally speaking, you should kill the whole process group but not only the process itself if you want to kill it's children too, with PHP you can add process B to its own process group, and kill the whole group then, here is the diff with your code:

--- limit.php   2012-08-11 20:50:22.000000000 +0800
+++ limit-new.php   2012-08-11 20:50:39.000000000 +0800
@@ -9,11 +9,13 @@
 if (-1 == $pid) {
     die('FORK_FAILED');
 } elseif ($pid == 0) {
+    $_pid = posix_getpid();
+    posix_setpgid($_pid, $_pid);
     exec($cmd);
     posix_kill(posix_getppid(), SIGALRM);
 } else {
     pcntl_signal(SIGALRM, create_function('$signo',"die('EXECUTE_ENDED');"));
     sleep($tl);
-    posix_kill($pid, SIGKILL);
+    posix_kill(-$pid, SIGKILL);
     die("TIMEOUT_KILLED : $pid");
 }

这篇关于标准输出影响SIGKILL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆