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.