这个问题至少有三个部分,所以请原谅我:
1)ESPRProcess有一个参数bInheritHandles,它使子进程继承父进程中的所有可继承句柄。此选项必须设置为TRUE,以允许父进程在STARTUPINFO参数中为子进程指定stdin、stdout和stderr句柄。
2)在Win32中,当同一个文件有多个句柄打开时,删除和重命名文件可能会失败。
3)Microsoft CRT的open()函数将默认创建可继承的句柄。另外,默认创建的文件句柄会遇到上面的问题2。
这种神奇的组合产生了以下操作问题:库A调用open(),并且不希望随后的重命名和删除失败。在进程的其他地方,另一个库B正在调用bInheritHandles设置为TRUE的OpenProcess(捕获标准输入/输出/错误)临时创建重复的句柄。现在偶尔库A的文件操作失败。自然库A和B由不同的人维护。我也知道另一个使用open()的库A'也有类似的问题。
这个kb article讨论了一个相关的问题和解决方案。但是它仍然依赖于在父进程中将bInheritHandles设置为TRUE的情况下调用WebProcess,所以它没有解决这个问题。
我想知道其他人是否遇到过这个问题,是否有一个众所周知的解决方案?
上面的知识库文章本质上暗示了调用bInheritHandles设置为TRUE的进程是不合理的,所以我倾向于修复库B,使它永远不会这样做。我会通过以下方式做到这一点:
1.创建一个挂起的中间进程(理想情况下,使用rundll运行库B中的自定义入口点),并将bInheritHandles设置为NULL。
1.创建stdin/out/err管道,并将其正确的末端向上传输到中间进程。
1.以某种方式将复制的句柄传递给中间进程。
1.恢复中间过程。
1.在中间进程中,使用来自父进程的管道填写STARTUPINFO,并调用STARTUPINFO Process,同时将bInheritHandles设置为TRUE。
这是一个好的策略还是有更好的解决方案?你会如何推荐在步骤3中将复制的句柄传递给中间进程?rundll +自定义入口点是在步骤1中设置中间进程的可靠方法吗?
3条答案
按热度按时间8xiog9wr1#
您可以使用
PROC_THREAD_ATTRIBUTE_HANDLE_LIST
扩展属性明确指定特定进程继承的句柄。Raymond Chen的博客文章"Programmatically controlling which handles are inherited by new processes in Win32"包含了实现这一点的示例代码。
简短的版本:
lpAttributeList
成员集需要Windows Vista,所以当这个问题最初被问到时可能没有解决OP问题,但是现在每个人都在使用Vista或更高版本,对吗?
iq3niunx2#
如果您可以访问实际的文件句柄,则可以在调用SetHandleProcess()之前使用SetHandleInformation()删除HANDLE_FLAG_INHERIT标志。
xxhby3vn3#
您可以使用ZwQuerySystemInformation(SystemHandleInformation,...)ntdll.dll函数查找您的进程拥有的所有句柄,然后按照雷米的建议,查找每个句柄上的所有SetHandleInformation,以删除HANDLE_FLAG_INHERIT标志。