Python script is killed from within, but the process doesn't die - php

I'm trying to execute a python script using php with an exec command like this:
exec("python /address/to/script.py");
I don't need the script to run to completion, so after it does what I need, I call sys.exit() from within it. Execution is passed back to the php script, which is great, however the python process is still running. I can see it in my server's process list. Is there more that's required to fully kill it?
Additional Info
The python script was written by a third party.
I know very little about python, just enough to add the sys.exit() call.

The script could still be executing some cleanup code, or you could be calling sys.exit() from a child process which will essentially be calling thread.exit(), leaving the parent process running.
Check that the sys.exit() call is in the main part of the script and that no error handling is interfering with the SystemExit exception, or alternatively you could try os._exit(). Also ensure that an ampersand (&) is not present within the command passed to exec() as this will cause the script to run as a background process.
Note that os._exit() is not favourable since it doesn't do any cleanup, and essentially ends the process immediately.
Edit To end the script from within your try block you could do something like this:
try:
# Existing Code
except SysExit:
os._exit() # quit the process
except:
# Existing error handling
Ideally the application logic should make use of message passing or something similar so that a child thread could notify the main thread that it should terminate.

Related

Stop a Python Script called in a PHP File when HTML page is exited

I have called a python script within my PHP page using the code below:
echo shell_exec("python object_detection_tutorial_cmsc265.py");
The python script generates image files in a loop until a certain condition is met. Example is the code below:
while (True):
cv2.imwrite('image' + str(loop) + '.png',image);
if (not condition):
break
When the HTML/PHP page is exited in the browser, I can see that the images are still increasing in number, that means the python is still executing. How will I stop the python script upon exiting PHP page?
Assuming your Python script is running in background, like this, you cannot.
If you want to handle this you will have to handle pid.
What following is kind of dirty, well using any kind of shell_exec is dirty anyway, but keep this in mind.
What you could do:
Make the Python script echo its pid at script startup
Use exec PHP function over shell_exec to get only script's first output line
Kill this pid before leaving your PHP script
Python
import os
print(os.getpid())
# your script
PHP
// code
$pid = intval(exec('python foo.py'))
exec("kill $pid")
Well, I'm not PHP developer, but google just told me it may be better to use posix_kill over exec("kill $pid").
Again, this is not clean code, it's hacky and depends a lot of the system.

Call Shell Command from PHP without considering output

I'm trying to write a cronjob which launches multiple processes that I want to run in parallel.
I'm using a foreach calling each command, but the command line waits for the output. I don't want it to put.
Was wondering if anyone ever used any library for this?
Add an ampersand after the command:
$ php task.php &
It will run that instance of php in the background and continue.
If you read the manual on passthru you'll notice it tells you how to avoid this...
If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.
So you can rely on UNIX fds to redirect output to something like /dev/null for example if you don't care about the output or to some file if you do want to save the output and this will avoid PHP waiting on the command to finish.
pssthru("somecommand > /some/path/to/file")

Detect when a script delays and allow it to skip or continue in PHP

I have a file, lets say file1.php, that within the script executes a file using: exec("php-cli -f _DAEMON.php") after executing the exec() command, it needs to run more code, the problem is that _DAEMON.php as its name says, is a Daemon and it will never stop running, so it freezes file1.php without allowing the rest of the code to run.
Is there a way to allow the code to continue executing even if exec("php-cli -f _DAEMON.php") has not finished. Or to detect if the code delays for more than x seconds/milliseconds, to continue?
Thanks.
Maybe try using a socket (curl might work with a low timeout, not sure if it'll kill the script though offhand). Not ideal, will add some overhead.
http://phplens.com/phpeverywhere/?q=node/view/254
Also, doriana_gd was probably referring to something like node.js, server side javascript

Executing a program from PHP hangs APACHE

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.

How do I know when the task from command line is finished?

This is really important as I could not find anything I am looking for in Google.
How do I know when the application (or is it more appropriate to call it a task?) executed by a command line is done? How does the PHP know if the task of copying several files are done if I do like this:
exec("cp -R /test/ /var/test/test");
Does the PHP script continue to go to next code even while the command is still running in background to make copies? Or does PHP script wait until the copy is finished? And how does a command line application notify the script when it's done (if it does)? There must be some kind of interaction going on.
php's exec returns a string so yes. Your webpage will freeze until the command is done.
For example this simple code
<?PHP
echo exec("sleep 5; echo HI;");
?>
When executed it will appear as the page is loading for 5 seconds, then it will display:
HI;
How does the PHP know if the task of copying several files are done if I do like this?
Php does not know, it simply just run the command and does not care if it worked or not but returns the string produced from this command. Thats why it better to use PHP's copy command because it returns TRUE/FALSE upon statistics. Or create a bash/sh script that will return 0/FALSE or 1/TRUE to determine if command was successful if you are going this route. Then you can PHP as such:
<?PHP
$answer = exec("yourScript folder folder2");
if ($answer=="1") {
//Plan A Worked
} else {
//Plan A FAILED try PlanB
}
?>
It waits until the exec call returns, whatever it returns.
However it might be that the exit call returns although the command it has started has not yet finished. That might be the case if you detach from the control, for example by explicitly specifying a "&" at the end of the command.

Categories