- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
Disclaimer
I am well aware that PHP might not have been the best choice in this case for a socket server. Please refrain from suggesting different languages/platforms - believe me - I've heard it from all directions.
在 Unix 环境 中工作并使用 PHP 5.2.17,我的情况如下 - 我用 PHP 构建了一个与 flash 客户端通信的套接字服务器。我的第一个障碍是每个传入连接都会阻塞顺序连接,直到它完成处理。我通过使用 PHP 的 pcntl_fork()
解决了这个问题。我成功地产生了许多子进程(将它们的 PID 保存在父进程中),这些子进程负责向其他客户端广播消息,因此“释放”父进程并允许它继续处理下一个连接[s]。
我现在的主要问题是处理/处理这些死亡/僵尸子进程的集合并终止它们。我已经(一遍又一遍地)阅读了 pcntl_fork() 的相关 PHP 手册页。并意识到父进程负责清理其子进程。当子进程执行 exit(0)
时,父进程会收到来自其子进程的 SIGNAL。我能够使用 pcntl_signal()
函数“捕获”该信号以设置一个信号处理程序。
我的 signal_handler 看起来像这样:
declare(ticks = 1);
function sig_handler($signo){
global $forks; // this is an array that holds all the child PID's
foreach($forks AS $key=>$childPid){
echo "has my child {$childPid} gone away?".PHP_EOL;
if (posix_kill($childPid, 9)){
echo "Child {$childPid} has tragically died!".PHP_EOL;
unset($forks[$key]);
}
}
}
我确实看到了两个 echo ,包括需要删除的相关且正确的子 PID,但似乎
posix_kill($childPid, 9)
我理解为 kill -9 $childPid
的同义词正在返回 TRUE,尽管它实际上并没有删除进程...
Returns TRUE on success or FALSE on failure.
我正在使用 ps
命令监视子进程。它们在系统上显示如下:
web5 5296 5234 0 14:51 ? 00:00:00 [php] <defunct>
web5 5321 5234 0 14:51 ? 00:00:00 [php] <defunct>
web5 5466 5234 0 14:52 ? 00:00:00 [php] <defunct>
如您所见,所有这些进程都是 PID 为 5234
我是不是遗漏了什么?我似乎已经设法让一切正常工作(确实如此),但我的系统上留下了无数的僵尸进程!
我的僵尸末日计划坚如磐石 -
但是即使 sudo kill -9
也没有杀死僵尸子进程,我到底能做什么呢?
这个问题我已经自己研究过了,如果你还受得了我的唠叨proceed at will .
最佳答案
I promise there is a solution at the end :P
好吧……10 天后,我们到了,我相信我已经解决了这个问题。我不想在已经很长的帖子上添加内容,所以我将在这个答案中包含一些我尝试过的东西。
服用 @sym's advice ,并阅读更多文档和对文档的评论, pcntl_waitpid()
描述状态:
If a child as requested by pid has already exited by the time of the call (a so-called
"zombie" process), the function returns immediately. Any system resources used by the child
are freed...
所以我设置了我的 pcntl_signal()
像这样的处理程序 -
function sig_handler($signo){
global $childProcesses;
$pid = pcntl_waitpid(-1, $status, WNOHANG);
echo "Sound the alarm! ";
if ($pid != 0){
if (posix_kill($pid, 9)){
echo "Child {$pid} has tragically died!".PHP_EOL;
unset($childProcesses[$pid]);
}
}
}
// These define the signal handling
// pcntl_signal(SIGTERM, "sig_handler");
// pcntl_signal(SIGHUP, "sig_handler");
// pcntl_signal(SIGINT, "sig_handler");
pcntl_signal(SIGCHLD, "sig_handler");
为了完成,我将包括我用于 fork 子进程的实际代码 -
function broadcastData($socketArray, $data){
global $db,$childProcesses;
$pid = pcntl_fork();
if($pid == -1) {
// Something went wrong (handle errors here)
// Log error, email the admin, pull emergency stop, etc...
echo "Could not fork()!!";
} elseif($pid == 0) {
// This part is only executed in the child
foreach($socketArray AS $socket) {
// There's more happening here but the essence is this
socket_write($socket,$msg,strlen($msg));
// TODO : Consider additional forking here for each client.
}
// This is where the signal is fired
exit(0);
}
// If the child process did not exit above, then this code would be
// executed by both parent and child. In my case, the child will
// never reach these commands.
$childProcesses[] = $pid;
// The child process is now occupying the same database
// connection as its parent (in my case mysql). We have to
// reinitialize the parent's DB connection in order to continue using it.
$db = dbEngine::factory(_dbEngine);
}
是的...这是评论与代码的 1:1 比例 :P
所以这看起来很棒,我看到了以下的 echo :
Sound the alarm! Child 12345 has tragically died!
然而,当套接字服务器循环执行下一次迭代时,socket_select()
函数抛出此错误失败:
PHP Warning: socket_select(): unable to select [4]: Interrupted system call...
服务器现在会挂起,除了来自根终端的手动终止命令之外,不会响应任何请求。
我不打算解释为什么会发生这种情况,或者我在那之后做了什么来调试它……只能说这是令人沮丧的一周……
喝了很多咖啡,眼睛酸痛,10 天后......
请敲鼓
提到here在 2007 年 php 套接字文档和 this 中的评论中关于 stuporglue 的教程(搜索“good parenting”),可以通过传递 SIGCHLD
来简单地“忽略”来自子进程 ( SIG_IGN
) 的信号到 pcntl_signal()
功能-
pcntl_signal(SIGCHLD, SIG_IGN);
引用该链接的博客文章:
If we are ignoring SIGCHLD, the child processes will be reaped automatically upon completion.
信不信由你 - 我包括了 pcntl_signal()
线,删除所有其他处理程序和处理 child 的事情并且它有效!没有了 <defunct>
进程悬而未决!
就我而言,我真的没有兴趣确切地知道子进程何时死亡,或者它是谁,我对它们根本不感兴趣 - 只是它们不会闲逛并使我的整个服务器崩溃:P
关于php - 终止从套接字服务器派生的僵尸子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9976441/
谁能解释一下 Server.MapPath(".")、Server.MapPath("~")、Server.MapPath(@"之间的区别\") 和 Server.MapPath("/")? 最佳答案
我不知道,为什么我们要使用 Server.UrlEncode() & Server.UrlDecode()?!在 QueryString 中我们看到 URL 中的任何内容,那么为什么我们要对它们进行编
我已经通过 WHM 在我的一个域上安装了 ssl 证书。网站正在使用 https://xyz.com . 但是它不适用于 https://www.xyz.com .我已经检查了证书,它也适用于 www
我已经使用 WMI 检测操作系统上是否存在防病毒软件,itz 正常工作并通过使用命名空间向我显示防病毒信息,例如 win xp 和 window7 上的名称和实例 ID:\root\SecurityC
我们有 hive 0.10 版本,我们想知道是否应该使用 Hive Server 1 或 Hive Server2。另一个问题是连接到在端口 10000 上运行的 Hive 服务器,使用 3rd 方工
我想在 C++ 中使用 Windows Server API 设置一个 HTTPS 服务器,我使用了示例代码,它在 HTTP 上工作正常,但我就是不能让它在 HTTPS 上工作。 (我不想要客户端 S
我写了一个非常基本的类来发送电子邮件。我用 smtp 服务器对其进行了测试,它工作正常,但是当我尝试使用我公司的交换服务器时,它给出了这个异常: SMTP 服务器需要安全连接或客户端未通过身份验证。服
我的应用程序包含一个“网关”DataSnap REST 服务器,它是所有客户端的第一个访问点。根据客户端在请求中传递的用户名(基本身份验证),请求需要重定向到另一个 DataSnap 服务器。我的问题
我有一个 Tomcat 服务器和一个 Glassfish4 服务器。我的 Servlet 在 Tomcat 服务器上启动得很好,但在 Glassfish4 服务器上给我一个“HTTP Status 4
我在 vmware 上创建了一个 ubuntu 服务器。我用它作为文件服务器。如果我通过托管虚拟机的计算机进行连接,则可以访问它。我无法从同一网络上的其他计算机执行此操作。提前致谢! 最佳答案 首先确
如何重启 Rails 服务器?我从 开始 rails server -d 所以服务器是分离的 我知道的唯一方法就是去做ps 辅助 | grep rails 并 kill -9关于过程#但是像这样杀死进
我实际上正在尝试找到编写一个简单的 XMPP 服务器的最佳方法,或者找到一个占用空间非常小的服务器。我只关心XMPP的核心功能(状态、消息传递、群组消息传递)。目前还在学习 XMPP 协议(proto
我实际上正在尝试找到编写简单 XMPP 服务器的最佳方法,或者找到一个占用空间非常小的方法。我只关心 XMPP 的核心功能(统计、消息、组消息)。目前也在学习 XMPP 协议(protocol),所以
我们正在尝试从 Java JAX-RS 适配器访问 SOAP 1.1 Web 服务。 我们正在使用从 WSDL 生成的 SOAP 客户端。 但是当解码 SOAP 故障时,我们得到以下异常: ... C
目前,我和许多其他人正在多个平台(Windows、OS X 和可能的 Linux)上使用 Python HTTP 服务器。我们正在使用 Python HTTP 服务器来测试 JavaScript 游戏
我有一个连续运行的服务器程序(C#/.NET 2.0 on Linux with mono),我想从 PHP 脚本连接到它以在网站上显示状态信息。 目的是创建一个(某种)实时浏览器游戏(无 Flash
所以我有一个单页客户端应用程序。 正常流程: 应用程序 -> OAuth2 服务器 -> 应用程序 我们有自己的 OAuth2 服务器,因此人们可以登录应用程序并获取与用户实体关联的 access_t
我们刚刚将测试 Web 服务器从 Server 2008 升级到 Server 2012 R2。我们有一个部署我们网站的批处理脚本。当它将站点推送到服务器时,它现在失败了。奇怪的是,我可以使用相同的发
建议一些加载SpagoBI服务器的方法,我尝试了所有方法来解析spagobi服务器。在 Catalina 中,错误是 - * SEVERE: Unable to process Jar entry [
当我们点击应用程序服务器(apache tomcat)时,它会创建一个线程来处理我们的请求并与 tomcat 连接,建立连接,tomcat 创建另一个线程来处理请求并将其传递给连接,连接线程将其传递给
我是一名优秀的程序员,十分优秀!