PRB: 继承意外的句柄时 CreateProcess 呼叫文章编号: 315939 - 查看本文应用于的产品创建子进程时使用 CreateProcess 函数调用在多线程环境中,子可能继承不旨在被继承的句柄。 如果两个线程同时创建子进程和重定向通过管道 STD 控点,则会发生此行为。在这种情况下在管道和在其中有可能一个子继承文件句柄用于其他子的进程的创建过程中没有 出现争用 条件。一个线程创建管道,并在创建过程的过程中该线程时,另一个线程也创建子进程。是可继承的 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 为您执行工作。在中间的进程中的任何意外继承句柄将绝对不能重复到子。这保证如果您在中间应用程序中调用 CreateProcessbInheritHandles 参数为 FALSE 指定。因为 Windows 始终将重复 STD 控点,即使 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 - 最后修改: 2006年11月21日 - 修订: 4.1 这篇文章中的信息适用于:- Microsoft Win32 Application Programming Interface?当用于
- the operating system: Microsoft Windows XP
- the operating system: Microsoft Windows 2000
- Microsoft Windows NT 4.0
| kbmt kbapi kbkernbase kbprb kbthread KB315939 KbMtzh |
机器翻译注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。 点击这里察看该文章的英文版: 315939
(http://support.microsoft.com/kb/315939/en-us/
)
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。 非常感谢!您的反馈将被用来改进我们的支持内容。更多的帮助选项,请访问 微软帮助和支持主页. | |