PRB: 子系繼承非預期的控點 CreateProcess 呼叫期間

重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。

按一下這裡查看此文章的英文版本:315939
徵狀
當您建立子處理序是利用 CreateProcess 函式呼叫在多執行緒環境中,子可能會繼承已不適合被繼承的控點。
發生的原因
如果兩個執行緒同時建立子處理程序,並重新導向標準控點,透過管道,就會發生這種行為。在這種情況下沒有 競爭 情形管道和裡面是可能繼承適用於其他子系的檔案控制代碼的一個子系的處理序建立過程。一個執行緒會建立管道] 及 [當該執行緒建立處理程序的程序中時另一個執行緒也建立子處理序。是可繼承 CreateProcess 呼叫期間應用程式中的所有控點都會跨越複製到子處理程序。
解決方案
如果要解決這個問題,包裝在關鍵區段的 [子建立程式碼]。這可防止任何意外繼承。正常這個方法,建立為 noninheritable 管道設定安全性描述元為 NULL。然後,設定您想要依照下列的範例程式碼所示,為可繼承繼承藉由使用 SetHandleInformation 函式呼叫子管道端點:
CRITICAL_SECTION    cs;HANDLE              hReadIn, hWriteIn;HANDLE              hReadOut, hWriteOut;HANDLE              hReadErr, hWriteErr;InitializeCriticalSection(&cs);EnterCriticalSection(&cs);if ( !CreatePipe(&hReadIn, &hWriteIn, NULL, 0) ){    // an error occurred}if ( !CreatePipe(&hReadOut, &hWriteOut, NULL, 0) ){    // an error occurred}if ( !CreatePipe(&hReadErr, &hWriteErr, NULL, 0) ){    // an error occurred}if ( !SetHandleInformation(hReadIn, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ){    // an error occurred}if ( !SetHandleInformation(hWriteOut, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ){    // an error occurred}if ( !SetHandleInformation(hWriteErr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ){    // an error occurred}STARTUP_INFO        si;PROCESS_INFORMATION pi;si.cb = sizeof(si);si.dwFlags = STARTF_USESTDHANDLES;si.hStdInput = hReadIn;si.hStdOutput = hWriteOut;si.hStdError = hWriteErr;if ( !CreateProcess( "child.exe",                     NULL,                     NULL, NULL,                     TRUE,                     NORMAL_PRIORITY_CLASS,                     lpEnvironment,                     &si, &pi) ){    // an error occurred}CloseHandle(hReadIn);CloseHandle(hWriteOut);CloseHandle(hWriteErr);LeaveCriticalSection(&cs);				
前述解決方案不會不來自沒有成本的筆記。在程式碼中的重要區段建立有時是雜亂,以及是來自的降低效能的價格。另一個解決此問題,而且也需要啟動子中繼應用程式的建立。 不過,本解決方案也有其缺點。這個方法主要的缺點是父代基本上失去輕鬆地與它會取得孩子的處理序 ID。如果父代需要處理序 ID,中繼程序必須傳送傳送它傳送回某種方式。

使用這個中間應用程式方法,可避免任何意外繼承由仰賴 Windows 為您執行工作。中繼程序中的任何意外繼承控點將絕對不會跨越複製給子。這會保證如果您指定 FALSE bInheritHandles 參數 CreateProcess 來呼叫,中間應用程式中。因為 Windows 將會永遠重複標準] 控點,甚至 bInheritHandles 設為 FALSE 時,仍將能複製管道控點。

父應用程式

HANDLE              hReadIn, hWriteIn;HANDLE              hReadOut, hWriteOut;HANDLE              hReadErr, hWriteErr;if ( !CreatePipe(&hReadIn, &hWriteIn, NULL, 0) ){    // an error occurred}if ( !CreatePipe(&hReadOut, &hWriteOut, NULL, 0) ){    // an error occurred}if ( !CreatePipe(&hReadErr, &hWriteErr, NULL, 0) ){    // an error occurred}STARTUP_INFO        si;PROCESS_INFORMATION pi;si.cb = sizeof(si);si.dwFlags = STARTF_USESTDHANDLES;si.hStdInput = hReadIn;si.hStdOutput = hWriteOut;si.hStdError = hWriteErr;if ( !CreateProcess( "Intermediate.exe",                     NULL,                     NULL, NULL,                     TRUE,                     NORMAL_PRIORITY_CLASS,                     lpEnvironment,                     &si, &pi) ){    // an error occurred}CloseHandle(hReadIn);CloseHandle(hWriteOut);CloseHandle(hWriteErr);				

中繼應用程式

STARTUP_INFO        si;PROCESS_INFORMATION pi;si.cb = sizeof(si);if ( !CreateProcess( "child.exe",                     NULL,                     NULL, NULL,                     FALSE,                     NORMAL_PRIORITY_CLASS,                     lpEnvironment,                     &si, &pi) ){    // an error occurred}				

警告:本文為自動翻譯

內容

文章識別碼:315939 - 最後檢閱時間:11/21/2006 15:37:38 - 修訂: 4.1

Microsoft Win32 Application Programming Interface

  • kbmt kbapi kbkernbase kbprb kbthread KB315939 KbMtzh
意見反應