执行程序从PHP APACHE挂起 [英] Executing a program from PHP hangs APACHE

查看:384
本文介绍了执行程序从PHP APACHE挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,感谢您事先的关注。

在过去的两个星期,我一直在努力的东西,我发疯。我有我的Windows中安装了Apache(2.2.22)和PHP(5.4.3),我试图调用PHP脚本中调用它在同一时间其他程序的程序。这两个程序都是用C / C ++和汇编MINGW32。关于到Windows的版本,我已经测试了Windows 2003 Server和Windows 7专业版和两个给我同样的问题。

让我来介绍一下这两种方案:

1)mytask.exe:这是一个程序,它是在后台执行,并且周期性地填充其状态到文件

2)job.exe:这是我想从PHP脚本中调用该程序。它的目标是产卵mytask.exe作为一个独立的过程(而不是作为一个线程)。

如果我从一个控制台窗口中运行以下命令,然后job.exe立即返回,留下mytask.exe在后台运行,直至结束。

 > job.exe产卵mytask.exe
作业ID = 18874111458879FED

请注意该job.exe转储被用于管理mytask.exe的标识符。例如:

 > job.exe状态18874111458879FED
RUNNING

我检查了,如果我从一个PHP脚本运行的第一个命令,PHP脚本的随机的块永远。如果我期待到Windows的任务管理器,我可以看到job.exe有一个行尸走肉般的状态。我可以断言,job.exe有效地达到正常的返回0;在其的main()常规语句,所以它似乎是木下的东西,在C运行时。
此外,如果我写一个简单的mytask.exe,仅仅睡了10秒钟,然后10秒过PHP脚本块(或块永继我刚刚提到的随机行为)。换句话说,我也没办法让job.exe产卵的过程,而不必等待它结束,当我叫job.exe从PHP脚本。

所以:有一些产卵mytask.exe和,现在当我做错了,来了这个题外话的第二部分。

我用的是WINAPI函数的CreateProcess()从job.exe产卵的任务。作为MSDN文档,我打电话用的CreateProcess bInheritHandles = FALSE ,以避免子进程产生的I / O死锁的PHP脚本。我还关闭进程处理由CreateProcess的()在PROCESS_INFORMATION结构中返回。我不这样做的唯一事情就是等待进程结束。在另一方面,对于到PHP的一面,我都试过执行exec() proc_open() PHP函数调用job.exe,但没有成功。

我最后的意见,不过,似乎是在以正确的方式,但他们不相信我,因为我不明白为什么他们莫名其妙地工作。事实是,如果不mytask.exe FCLOSE(标准输出)睡觉前,那么PHP脚本立即返回。但是,如何?我告诉的CreateProcess()不继承手柄,所以为什么我得到这些结果?反正我不能与此补丁坚持,因为job.exe启动的程序可能不知道谁喊他们,所以从这些程序关闭stdout不是一个很好的解决方案。在UNIX中,事情是这么简单...一个只是调用叉(),关闭标准流,然后调用的execve 调用该程序。在Windows中,我也试着创建具有的CreateThread()(模拟叉()),然后调用从该线程的CreateProcess()关闭标准流后的包装线......但收盘job.exe的流过!

所有这些问题可以在合成一个单一:我如何从PHP执行创建其他进程的程序

我希望有人能够说明在这个问题上一些轻......非常感谢你们!


解决方案

我想我已经钉了解决方案,它是分为两部分:

1)关于主进程停止,直到子进程结束的事实。

由于MSDN文档,这是定义的CreateProcess()

  BOOL WINAPI的CreateProcess(
  _In_opt_ LPCTSTR lpApplicationName,
  _Inout_opt_ LPTSTR lpCommandLine,
  _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
  标签:APIWinHTTP BOOL bInheritHandles,
  标签:APIWinHTTP DWORD dwCreationFlags,
  _In_opt_ LPVOID lpEnvironment,
  _In_opt_ LPCTSTR lpCurrentDirectory,
  标签:APIWinHTTP LPSTARTUPINFO lpStartupInfo,
  _Out_ LPPROCESS_INFORMATION lpProcessInformation
);

正如我在我的问题说,我通过 FALSE bInheritHandles ,但我也路过 0 dwCreationFlags 。更多研究的一点点后,我发现有一个叫标志 DETACHED_PROCESS ,为此,MSDN说:

对于控制台程序,新的进程不会继承其父的控制台(默认值)。新方法可以在稍后的时间调用AllocConsole函数来创建控制台。欲了解更多信息,请参见控制台的创建。

现在,尽管子进程继续执行的事实job.exe立即返回。

2)关于事实调用exec当PHP脚本随机挂起()

这似乎是PHP的一个bug。在PHP会话的上下文中运行执行exec()家庭功能可以让Apache随机挂,是需要重新启动服务器。我发现在互联网一个线程在其中一个用户注意到,在会议闭幕(直通 session_write_close())之前调用执行exec()将prevent从悬挂的脚本。这同样适用于在 proc_open / proc_close 功能。所以,我的脚本现在看起来是这样的:

  session_write_close(); // proc_open之前关闭会话()
$ PROC = proc_open(CMD $,$ pipedesc,$管道);
//做的东西与管...
// ...并关闭管道
$ RETVAL = proc_close($ PROC);
在session_start(); //恢复会话

希望这有助于。

Hello and thank you in advance for your interest.

During the past two weeks I've been struggling with something that is driving me nuts. I have APACHE (2.2.22) and PHP (5.4.3) installed on my Windows box and I'm trying to call a program from a PHP script which calls another program at the same time. Both programs are written in C/C++ and compiled with MINGW32. Regarding to Windows version, I've tested Windows 2003 Server and Windows 7 Professional and both give me the same problems.

Let me introduce these two programs:

1) mytask.exe: this is a program that is to be executed in background and that periodically populates its status to a file.

2) job.exe: this is the program I want to call from the PHP script. Its goal is to spawn mytask.exe as an independent process (not as a thread).

If I run from a Console window the command below, then job.exe immediately returns and leaves mytask.exe running on the background until it terminates.

> job.exe spawn mytask.exe
jobid=18874111458879FED

Note that job.exe dumps an identifier which is used to manage mytask.exe. For example:

> job.exe status 18874111458879FED
RUNNING

I've checked that if I run the first command from a PHP script, the PHP script randomly blocks forever. If I look to the Windows's task manager, I can see that job.exe is there in a zombie-like state. I can assert that job.exe effectively reaches the usual return 0; statement in its main() routine, so it seems to be something under the wood, in the C runtime. Furthermore, if I write a simple mytask.exe that simply sleeps for 10 seconds then the PHP script blocks for 10 seconds too (or blocks forever following the random behavior I've just mentioned). In other words, I have no way to make job.exe spawning a process without waiting for it to end, when I call job.exe from a PHP script.

So: there's something I'm doing wrong when spawning mytask.exe and, now, here comes the second part of this digression.

I use the WINAPI function CreateProcess() to spawn the tasks from job.exe. As of the MSDN documentation, I call CreateProcess with bInheritHandles = FALSE, to avoid the child process to yield I/O deadlocks with the PHP script. I also close the process handles returned by CreateProcess() in the PROCESS_INFORMATION structure. The only thing I don't do is waiting for the process to end. On the other hand, regarding to the PHP side, I've tried both exec() and proc_open() PHP functions to call job.exe with no success.

My last observations, though, seem to be in the right way, yet they do not convince me because I don't understand why they work somehow. The fact is that if mytask.exe does fclose(stdout) before sleeping, then the PHP script returns immediately. BUT, HOW??? I told CreateProcess() to not inherit handles, so why am I getting these results? Anyway, I cannot stick with this patch because programs launched by job.exe may not know about who is calling them, so closing stdout from those programs is not a good solution. In UNIX, things are so simple... One just calls fork(), closes standard streams and then calls execve to call the program. In Windows, I've also tried to create a wrapper thread with CreateThread() (to emulate fork()) and then call CreateProcess() from that thread after closing standard streams... but that closed the streams of job.exe too!

All this question could be synthesized in a single one: how can I execute from PHP a program that creates other processes?

I hope somebody could shed some light on this issue... Thank you very much!

解决方案

I think I've nailed the solution, which is divided in two parts:

1) Regarding the fact the main process stops until the child process ends.

As of MSDN documentation, this is the definition of CreateProcess():

BOOL WINAPI CreateProcess(
  _In_opt_     LPCTSTR lpApplicationName,
  _Inout_opt_  LPTSTR lpCommandLine,
  _In_opt_     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_         BOOL bInheritHandles,
  _In_         DWORD dwCreationFlags,
  _In_opt_     LPVOID lpEnvironment,
  _In_opt_     LPCTSTR lpCurrentDirectory,
  _In_         LPSTARTUPINFO lpStartupInfo,
  _Out_        LPPROCESS_INFORMATION lpProcessInformation
);

As I said in my question, I pass FALSE to bInheritHandles, but I was also passing 0 to dwCreationFlags. After a little bit of more research, I found that there's a flag called DETACHED_PROCESS, for which MSDN says:

For console processes, the new process does not inherit its parent's console (the default). The new process can call the AllocConsole function at a later time to create a console. For more information, see Creation of a Console.

Now, job.exe returns immediately despite the fact the child process continues its execution.

2) Regarding the fact the PHP script randomly hangs when calling exec()

It seems to be a bug of PHP. Running exec() family functions in the context of a PHP session may make APACHE to randomly hang, being necessary to restart the server. I found a thread in the Internet in which a user noticed that closing the session (thru session_write_close()) before calling exec() would prevent the script from hanging. The same applies for the proc_open/proc_close functions. So, my script now looks like this:

session_write_close();  //Close the session before proc_open()
$proc = proc_open($cmd,$pipedesc,$pipes);
//do stuff with pipes... 
//... and close pipes
$retval = proc_close($proc);
session_start(); //restore session

Hope this helps.

这篇关于执行程序从PHP APACHE挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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