Discussion:
run a process in background on Windows
Jan Vávra
2014-10-08 12:54:18 UTC
Permalink
Hello,
there are several tips how to run a child process ($cmd) in background
on Windows. Firstly I used popen:
|function execInBackground($cmd)
{
$cmd = 'start /B "" ' . $cmd;
pclose(popen($cmd, "r"));
}

Using of popen has unexpected side effect. If somebody locks a file, the
child process inherits the file lock Windows handle and the file is
locked by the child process. The child process application don't know
about it.

I needed to call a child simple http server that wraps the java code and
I made a file locks in php to make a critical section for launching the
simple java http server. And the lock is held forever by the java child
process.

This problem is caused by the inherit_handle parameter set to TRUE in
CreateProcess function in the proc_open Windows implementation.

This problem is more probable. If someone uses log4php the log files are
file locked and the child process holds the logs. So the logs cannot be
deleted etc.

I also tried to use
function execInBackground($cmd)
{
$cmd = "c:\tmp\PSTools\PsExec.exe -d ".$cmd;
exec($cmd);
}
This implementation doesn't have problem with file locks as described
above but opens a console window for a child process.

So I had to write my PsExec.exe equivalent in c++:
int main(int argc, char **argv)
{
DWORD cpError = ERROR_SUCCESS;
if (argc>1)
{
std::string cmdline = argv[1];
for (int i=2; i<argc; i++)
{
cmdline=cmdline+" "+argv[i];
}

STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );

// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line).
(LPSTR)cmdline.c_str(), // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_NO_WINDOW, // Creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
cpError = GetLastError();
printf( "CreateProcess failed (%d).\n", cpError );
return 1;
}

// DONT wait until child process exits.
//WaitForSingleObject( pi.hProcess, INFINITE );

// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}

return cpError;
}|

I think It would be nice to have a function exec_in_background(.) that
does it directly in the php core.
Jan.
Jim Lucas
2014-10-08 15:21:44 UTC
Permalink
Post by Jan Vávra
Hello,
there are several tips how to run a child process ($cmd) in background on
|function execInBackground($cmd)
{
$cmd = 'start /B "" ' . $cmd;
pclose(popen($cmd, "r"));
}
Using of popen has unexpected side effect. If somebody locks a file, the child
process inherits the file lock Windows handle and the file is locked by the
child process. The child process application don't know about it.
I needed to call a child simple http server that wraps the java code and I
made a file locks in php to make a critical section for launching the simple
java http server. And the lock is held forever by the java child process.
This problem is caused by the inherit_handle parameter set to TRUE in
CreateProcess function in the proc_open Windows implementation.
This problem is more probable. If someone uses log4php the log files are file
locked and the child process holds the logs. So the logs cannot be deleted etc.
I also tried to use
function execInBackground($cmd)
{
$cmd = "c:\tmp\PSTools\PsExec.exe -d ".$cmd;
exec($cmd);
}
This implementation doesn't have problem with file locks as described above
but opens a console window for a child process.
int main(int argc, char **argv)
{
DWORD cpError = ERROR_SUCCESS;
if (argc>1)
{
std::string cmdline = argv[1];
for (int i=2; i<argc; i++)
{
cmdline=cmdline+" "+argv[i];
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line).
(LPSTR)cmdline.c_str(), // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_NO_WINDOW, // Creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
cpError = GetLastError();
printf( "CreateProcess failed (%d).\n", cpError );
return 1;
}
// DONT wait until child process exits.
//WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
return cpError;
}|
I think It would be nice to have a function exec_in_background(.) that does it
directly in the php core.
Jan.
PCNTL [1] will allow you to fork a process. It isn't usually included in the
standard build of PHP.

1) http://php.net/manual/en/book.pcntl.php
--
Jim Lucas

http://www.cmsws.com/
http://www.cmsws.com/examples/
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Christoph Becker
2014-10-08 15:50:27 UTC
Permalink
Post by Jim Lucas
Post by Jan Vávra
I think It would be nice to have a function exec_in_background(.) that does it
directly in the php core.
PCNTL [1] will allow you to fork a process. It isn't usually included in the
standard build of PHP.
1) http://php.net/manual/en/book.pcntl.php
However, PCNTL is not available on Windows at all.
--
Christoph M. Becker
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
TR Shaw
2014-10-08 16:08:18 UTC
Permalink
Post by Christoph Becker
Post by Jim Lucas
Post by Jan Vávra
I think It would be nice to have a function exec_in_background(.) that does it
directly in the php core.
PCNTL [1] will allow you to fork a process. It isn't usually included in the
standard build of PHP.
1) http://php.net/manual/en/book.pcntl.php
However, PCNTL is not available on Windows at all.
If you can run that unix env on windows (used to remember the name but I havent run windows in years) you could use exec in php and invoke a fork using the "&" shell command so you would do a "& php phpapp.php"


Tom
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Frank Arensmeier
2014-10-08 17:49:13 UTC
Permalink
Post by Christoph Becker
Post by Jim Lucas
Post by Jan Vávra
I think It would be nice to have a function exec_in_background(.) that does it
directly in the php core.
PCNTL [1] will allow you to fork a process. It isn't usually included in the
standard build of PHP.
1) http://php.net/manual/en/book.pcntl.php
However, PCNTL is not available on Windows at all.
If you can run that unix env on windows (used to remember the name but I havent run windows in years) you could use exec in php and invoke a fork using the "&" shell command so you would do a "& php phpapp.php”
Cygwin
https://www.cygwin.com

/frank
Tom
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Szopen Xiao
2014-10-09 01:50:36 UTC
Permalink
you can use vbs script run cmd.exe and invoke php script with a bat script
the vbs like below:

Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c 123.bat",vbhide

in 123.bat invoke php script
Post by Jan Vávra
Hello,
there are several tips how to run a child process ($cmd) in background on
|function execInBackground($cmd)
{
$cmd = 'start /B "" ' . $cmd;
pclose(popen($cmd, "r"));
}
Using of popen has unexpected side effect. If somebody locks a file, the
child process inherits the file lock Windows handle and the file is locked
by the child process. The child process application don't know about it.
I needed to call a child simple http server that wraps the java code and I
made a file locks in php to make a critical section for launching the
simple java http server. And the lock is held forever by the java child
process.
This problem is caused by the inherit_handle parameter set to TRUE in
CreateProcess function in the proc_open Windows implementation.
This problem is more probable. If someone uses log4php the log files are
file locked and the child process holds the logs. So the logs cannot be
deleted etc.
I also tried to use
function execInBackground($cmd)
{
$cmd = "c:\tmp\PSTools\PsExec.exe -d ".$cmd;
exec($cmd);
}
This implementation doesn't have problem with file locks as described
above but opens a console window for a child process.
int main(int argc, char **argv)
{
DWORD cpError = ERROR_SUCCESS;
if (argc>1)
{
std::string cmdline = argv[1];
for (int i=2; i<argc; i++)
{
cmdline=cmdline+" "+argv[i];
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line).
(LPSTR)cmdline.c_str(), // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_NO_WINDOW, // Creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
cpError = GetLastError();
printf( "CreateProcess failed (%d).\n", cpError );
return 1;
}
// DONT wait until child process exits.
//WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
return cpError;
}|
I think It would be nice to have a function exec_in_background(.) that
does it directly in the php core.
Jan.
Loading...