gpt4 book ai didi

python - 恢复创建的进程的线程挂起,丢失了线程句柄

转载 作者:行者123 更新时间:2023-11-28 19:29:19 26 4
gpt4 key购买 nike

在 Windows 上,Python (2) 的标准库例程 subprocess.Popen允许您为 CreateProcess 指定任意标志,并且您可以从 Popen 返回的对象访问新创建进程的 process 句柄。但是,在 Popen 返回之前,库关闭了新创建进程的初始线程的 thread 句柄。

现在,我需要创建一个暂停的进程(创建标志中的 CREATE_SUSPENDED),以便我可以在它有机会执行任何代码之前对其进行操作(具体来说,将其附加到作业对象) .但是,这意味着我需要线程句柄才能将进程从挂起中释放出来(使用 ResumeThread)。要恢复线程句柄,我能找到的唯一方法是使用“工具帮助”库遍历整个系统上的所有线程(例如,参见 this question and answer)。这有效,但我不喜欢它。具体来说,我担心每次需要创建进程时拍摄系统上所有线程的快照会过于昂贵。 (较大的应用程序是一个测试套件,使用进程进行隔离;它以每秒数十到数百个进程的速度创建和销毁进程。)

所以,问题是:是否有一种更有效的方法来恢复执行被 CREATE_SUSPENDED 挂起的进程,如果您只有进程句柄,以及 Python 2 标准库的功能(包括 ctypes,但 winapi 附加组件)? Vista 和更高版本的技术是可以接受的,但首选 XP 兼容性。

最佳答案

我找到了一个更快的方法;不幸的是,它依赖于一个未记录的 API,NtResumeProcess。这确实听起来像 - 获取进程句柄并将 ResumeThread 的等效项应用于进程中的每个线程。使用它的 Python/ctypes 代码看起来像

import ctypes
from ctypes.wintypes import HANDLE, LONG, ULONG

ntdll = ctypes.WinDLL("ntdll.dll")
RtlNtStatusToDosError = ntdll.RtlNtStatusToDosError
NtResumeProcess = ntdll.NtResumeProcess

def errcheck_ntstatus(status, *etc):
if status < 0: raise ctypes.WinError(RtlNtStatusToDosError(status))
return status

RtlNtStatusToDosError.argtypes = (LONG,)
RtlNtStatusToDosError.restype = ULONG
# RtlNtStatusToDosError cannot fail

NtResumeProcess.argtypes = (HANDLE,)
NtResumeProcess.restype = LONG
NtResumeProcess.errcheck = errcheck_ntstatus

def resume_subprocess(proc):
NtResumeProcess(int(proc._handle))

我测得,在一台闲置的 Windows 7 虚拟机上,使用这种技术比使用 Toolhelp 的过程设置开销要少大约 20%。考虑到 Toolhelp 的工作方式,正如预期的那样,系统中存在的线程越多,性能增量就越大——无论它们是否与相关程序有任何关系。

考虑到 NtResumeProcess 及其对应的 NtSuspendProcess 的明显通用实用性,我想知道为什么它们从未被记录并提供 kernel32 包装器。它们被少数核心系统 DLL 和 EXE 使用,据我所知,它们都是 Windows 错误报告机制的一部分(faultrep.dllwerui.dllwerfault.exedwwin.exe 等),并且似乎没有在记录的名称下重新公开功能。这些函数似乎不太可能在不更改名称的情况下更改它们的语义,但可能应该准备一个防御性编码的程序让它们消失(我想回到工具帮助)。

关于python - 恢复创建的进程的线程挂起,丢失了线程句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34551464/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com