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.