PHP-在客户端断开连接时杀死exec [英] PHP - kill exec on client disconnect

查看:172
本文介绍了PHP-在客户端断开连接时杀死exec的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我的C ++应用程序具有非常原始的Web前端.客户端(Web浏览器)进入php站点并用参数填写表格. (在提交后)比php调用 exec ,应用程序完成了工作. 应用程序的工作时间可能超过一分钟,并且需要大量的RAM.

是否有可能检测到与客户端的断开连接(例如,Web浏览器中的选项卡关闭).我想这样做,因为断开客户端连接后将无法看到计算结果,因此我可以终止应用程序并释放服务器上的一些RAM.

感谢您的帮助或建议.

解决方案

只要C ++程序在运行时生成输出,而不是在终止之前生成所有输出,请使用passthru()而不是exec(). /p>

这会导致PHP在生成内容时将输出刷新到客户端,这使PHP能够检测到客户端何时断开连接.当客户端断开连接并立即终止子进程时,PHP将终止(只要未设置ignore_user_abort()即可).

示例:

<?php

  function exec_unix_bg ($cmd) {
    // Executes $cmd in the background and returns the PID as an integer
    return (int) exec("$cmd > /dev/null 2>&1 & echo $!");
  }
  function pid_exists ($pid) {
    // Checks whether a process with ID $pid is running
    // There is probably a better way to do this
    return (bool) trim(exec("ps | grep \"^$pid \""));
  }

  $cmd = "/path/to/your/cpp arg_1 arg_2 arg_n";

  // Start the C++ program
  $pid = exec_unix_bg($cmd);

  // Ignore user aborts to allow us to dispatch a signal to the child
  ignore_user_abort(1);

  // Loop until the program completes
  while (pid_exists($pid)) {

    // Push some harmless data to the client
    echo " ";
    flush();

    // Check whether the client has disconnected
    if (connection_aborted()) {
      posix_kill($pid, SIGTERM); // Or SIGKILL, or whatever
      exit;
    }

    // Could be done better? Only here to prevent runaway CPU
    sleep(1);

  }

  // The process has finished. Do your thang here.

要收集程序的输出,请将输出重定向到文件而不是/dev/null.我怀疑您需要为此安装pcntl以及posix,因为PHP手册指出SIGxxx常量是由pcntl扩展名定义的-尽管我从来没有安装过另外的pcntl,所以我我不确定这两种方式.


I have very primitive web front-end for my C++ application. Client (web browser) is enters php site and fills form with parameters. Than (after post submit) php calls exec and application does its work. Application can work longer than minute and requires pretty large amount of RAM.

Is there any possibility to detect disconnecting from client (for example closure of tab in web browser). I want to do this, because after disconnecting client will not be able to see result of computations, so I can kill application and free some RAM on server.

Thanks for any help or suggestions.

解决方案

As long as the C++ program produces output while running, rather than generating all the output just prior to termination, use passthru() instead of exec().

This causes PHP to flush the output to the client as the content is produced, which allows PHP to detect when clients disconnect. PHP will terminate when the client disconnects and kill the child process immediately (as long as ignore_user_abort() is not set).

Example:

<?php

  function exec_unix_bg ($cmd) {
    // Executes $cmd in the background and returns the PID as an integer
    return (int) exec("$cmd > /dev/null 2>&1 & echo $!");
  }
  function pid_exists ($pid) {
    // Checks whether a process with ID $pid is running
    // There is probably a better way to do this
    return (bool) trim(exec("ps | grep \"^$pid \""));
  }

  $cmd = "/path/to/your/cpp arg_1 arg_2 arg_n";

  // Start the C++ program
  $pid = exec_unix_bg($cmd);

  // Ignore user aborts to allow us to dispatch a signal to the child
  ignore_user_abort(1);

  // Loop until the program completes
  while (pid_exists($pid)) {

    // Push some harmless data to the client
    echo " ";
    flush();

    // Check whether the client has disconnected
    if (connection_aborted()) {
      posix_kill($pid, SIGTERM); // Or SIGKILL, or whatever
      exit;
    }

    // Could be done better? Only here to prevent runaway CPU
    sleep(1);

  }

  // The process has finished. Do your thang here.

To collect the program's output, redirect the output to a file instead of /dev/null. I suspect you will need pcntl installed as well as posix for this, since the PHP manual indicates the SIGxxx constants are defined by the pcntl extension - although I have never had one installed without the other so I'm not sure either way.

这篇关于PHP-在客户端断开连接时杀死exec的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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