2011年12月13日 星期二

CreateProcess 呼叫另一個程式

同事在用 CreateProcess 呼叫我寫的程式的時候
有出點問題

 把 CreateProcess 做個重點整理
( All Info is describe in Jeffery Ritcher's Windows Via C/C++, Chap 4 )

1. 同事用 loop 一直判斷 子Process 結束了沒,這是很不好的做法,浪費CPU時間。
 if ( GetExitCodeProcess() == STILL_ACTIVE )

而且,如果子程式笨笨的 不小心把 STILL_ACTIVE (259, 0x103) 做為傳回值之一會讓Parent Process 誤判,這會是個很不容易發現的錯誤。

2. CreateProcess 後, PROCESS_INFORMATION 會回傳 2 個handle, 一個Process Handle, 一個Thread Handle。記得沒用的話要使用CloseHandle關掉,
不然的話就得等到Parent Process 整個結束的時候才會free。
其概念就是 系統在創建 Kernel Object 時會把reference counter 加一,
reference counter 為0時 才會真正destroy object. 所以回傳的 PROCESS_INFORMATION  Process Handle, 在 child process 結束後並不會被free, (否則如何 call GetExitCodeProcess?) 必需自己手動CloseHandle。所以一個Process 的Handle 可能會活得比Process更久. This is a feature, not a bug.

3. 整個流程如下

PROCESS_INFORMATION pi;
DWORD dwExitCode;

// Spawn the child process.
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess) {
// Close the thread handle as soon as it is no longer needed!
CloseHandle(pi.hThread);
// Suspend our execution until the child has terminated.
WaitForSingleObject(pi.hProcess, INFINITE);
// The child process terminated; get its exit code.
GetExitCodeProcess(pi.hProcess, &dwExitCode);
// Close the process handle as soon as it is no longer needed.
CloseHandle(pi.hProcess);
}

第一個CloseHandle(hThread) 並不會真正把 child process 的primary thread 停掉 (因為 usage counter 並不為0) , 所以這也是沒事就在第一行先把它 close掉的原因)

As already mentioned, creating a new process causes the system to create a process kernel object and a thread kernel object. At creation time, the system gives each object an initial usage count of 1. Then, just before CreateProcess returns, the function opens with full access to the process object and the thread object, and it places the process-relative handles for each in the hProcess and hThread members of the PROCESS_INFORMATION structure. When CreateProcess opens these objects internally, the usage count for each becomes 2.

沒有留言: