简体   繁体   English

在Linux中使用PHP的posix_kill()导致奇怪的行为

[英]Using PHP's posix_kill() in linux causing strange behaviour

I am creating a web page which will be used to monitor and control some custom C programs. 我正在创建一个用于监视和控制某些自定义C程序的网页。 I've created a page which will start/stop a C program 'launcher' (nice generic name) which then forks and creates a number of child processes. 我创建了一个页面,该页面将启动/停止C程序“启动器”(很好的通用名称),然后分叉并创建多个子进程。 The starting works fine - exec("cd launcher_dir; nohup ./launcher > outfile 2>&1 &"); 启动正常exec("cd launcher_dir; nohup ./launcher > outfile 2>&1 &");

The stopping is where there's a problem. 停下来就是有问题的地方。 After clicking the stop button one of two things happens at random. 单击停止按钮后,随机发生两件事之一。 Either there is a browser error page (101 Connection Reset or 324 Empty Response) or the page is loaded twice, but you only see it the second time. 可能是浏览器错误页面(“ 101连接重置”或“ 324空响应”)或页面被加载了两次,但是您仅第二次看到它。 The reason I know it loads twice is because of debugging messages in the code. 我知道它加载两次的原因是由于代码中的调试消息。 In both cases the launcher process is killed (sent SIGTERM). 在这两种情况下,启动器进程均被终止(已发送SIGTERM)。 But if the page loads twice, on the first time it kills launcher (nothing loads on the page for this part) and the second time it checks and finds that no launcher process is running and displays a message: "Launcher is not running". 但是,如果页面加载两次,则第一次它会杀死启动器(此部分页面上没有加载),第二次它检查并发现没有启动器进程正在运行,并显示一条消息:“ Launcher未运行”。

I am writing debug messages into a file and found that the reload occurs at a somewhat variable line in the php code (sometimes a certain debug message will print, other times it won't.) Also, php error reporting is set to ALL and no errors are given. 我将调试消息写入文件,发现重新加载发生在php代码中的某个可变行上(有时会打印某些调试消息,而其他时候则不会。)此外,php错误报告设置为ALL,并且没有错误。

Launcher catches SIGTERM, sends SIGTERM to it's child processes in turn, and then calls exit(0). 启动器捕获SIGTERM,依次将SIGTERM发送到其子进程,然后调用exit(0)。

Interestingly if SIGKILL is used to kill launcher, the php works fine and as expected, however this doesn't allow launcher to shut down nicely. 有趣的是,如果使用SIGKILL杀死启动器,则php可以正常运行,并且符合预期,但是这不允许启动器很好地关闭。 What could be happening here? 这里会发生什么?

Here is the relevant php code: 这是相关的php代码:

function stop_launcher(){
    $pid = get_launcher_pid(); // Definitely returns the correct pid
    debug_message("stop_launcher called, pid = ".$pid);
    if ($pid == "") {
        // If no 'connection reset' error occurs this is displayed
        // after first executing the else branch. Why is the php being run twice?
        print "Launcher doesn't seem to be running.. <br />";
        exit;
    } else {
        debug_message("killing");
        posix_kill(intval($pid), 15); //SIGTERM
        debug_message("kill finished"); // Sometimes this message is written, sometimes                      not
        if (ps_exists($pid)) { // Definitely works. This never gets displayed
            print "Shutdown failed. Try again</br>";
            exit;
        } 
    }
}

function debug_message($message){
    $fh = fopen(".debug", 'a') or die("can't open file");
    fwrite($fh, date("-r").":  ".$message."\n");
    fclose($fh);
}

Any suggestions are appreciated! 任何建议表示赞赏!

It turns out that this was one of those bugs that makes you feel stupid! 事实证明,这是使您感到愚蠢的错误之一! The launcher program was accidentally killing it's process group... 启动器程序意外杀死了它的进程组...

Launcher is the shell. 启动器是外壳。 Some shells will send SIGTERM to their children if they receive SIGTERM. 如果某些shell收到SIGTERM,则会将SIGTERM发送给其子级。 Changing "nohup" to "exec nohup" should get rid of the problem. 将“ nohup”更改为“ exec nohup”应该可以解决此问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM