TerminateProcess 的文档部分说:

This function stops execution of all threads within the process and requests
cancellation of all pending I/O.

...

TerminateProcess is asynchronous; it initiates termination and returns
immediately. If you need to be sure the process has terminated, call the
WaitForSingleObject function with a handle to the process.

如果您使用 TerminateProcess 来执行进程自杀,这会导致一些不确定性,如下所示:
TerminateProcess(GetCurrentProcess(), exit_code)

从逻辑上讲,这应该足够了,但是文档说之后可能会继续执行,如果由于错误导致进程处于不确定状态而调用 TerminateProcess,这很危险。

我发现最接近确认不需要等待自杀的是 _invoke_watson 的源代码:
C:\Program Files (x86)\Windows Kits\10\Source\10.0.10240.0\ucrt\misc\invalid_parameter.cpp

这个函数所做的最后一件事是调用 TerminateProcess 本身——无需等待。

获得确定性会很好,我想在这里问这个问题,以便答案可以作为文档的补充。

最佳答案

我从一个不希望自己将其发布在这里的离线人那里得到了这个答案:

我对用户模式文档的看法是 TerminateProcess 通常是一个进程对另一个进程所做的事情,并且文档是为这种普遍性而编写的,从这个意义上说是正确和合理的。

给 TerminateProcess 一个其他进程的句柄,你当然希望调用返回给你继续操作。

文档指出的是,调用的成功并不意味着另一个进程已经终止,只是它的终止已经成功进行。

如果你依赖的不止这些,那么你肯定做错了什么。因此,调查究竟什么是可靠的,甚至思考它,对我来说似乎从来都不是很有用。尽管我很困扰,但我认为这意味着当 TerminateProcess 返回给您时,另一个进程及其所有线程都已被标记为已终止 - 从字面上看,它们在 ETHREAD 中设置了 Terminated 位 - 但是继续执行 APC,通常用于完成或取消 I/O 之类的事情。尽管这种持续执行受到很大限制,但可能需要一些不确定的时间。因此,如果您需要知道所有执行都已完成,您可以观察进程是否收到信号。

当然,调用 TerminateProcess 来终止另一个进程是一件很残忍的事情,文档中也提到了这一点。

相同的过程

调用 TerminateProcess 来终止你自己的进程也同样残酷。除了一个异常(exception),它在很大程度上是最后的手段,即使在这种情况下,也是一个非常绝望的手段。任何这样做的人都必须有比调用可能返回的更大的问题,否则他们肯定会调用显式不返回的 ExitProcess (但可能会使进程陷入死锁)。

通过 TerminateProcess 自终止引入了一种情况,即正在终止的线程之一是当前线程。终止后的 APC 处理不会为其激活:在 Windows 7 内核中,请参阅 PspTerminateThreadByPointer,这再次使当前线程的用户模式终止转到不返回的 PspExitThread 而不是为最后退出。

所以,我的理解是使用 -1 作为句柄的 TerminateProcess 不会返回,但是如果您在内核中为调用线程执行的最后一条指令,您可以看到您的进程中的其他线程可能仍会执行到处理 APC,但您的 APC 队列已耗尽,即将被切换离开,永远不会回来。事实上,如果此时您的线程不知何故有一个 APC 需要处理,内核就会进行错误检查!

顺便说一下,TerminateProcess 的异常是残酷的,它本质上是 NTDLL 所做的最后一件事,即使是通过 ExitProcess 进行相对温和的自我终止。众所周知,但它总是让我感到惊讶,为了处理 RtlExitUserProcess,NTDLL 调用 NtTerminateProcess 两次。首先,有用户模式清理和对 NtTerminateProcess 的调用,将 NULL 作为句柄。如果这成功了,就会有更多的用户模式清理,以调用 NtTerminateProcess 并给出 -1 作为句柄结束。

好吧,最后一个调用正是您从 TerminateProcess 获得的,以 -1 作为句柄。当您通过 TerminateProcess 自行终止时,您只是跳过了在用户模式和内核模式下从 ExitProcess 获得的清理工作。无论如何,当TerminateProcess 实际上由NTDLL 作为ExitProcess 的结束完成时,它显然不会返回。

关于windows - TerminateProcess(GetCurrentProcess(), exit_code) 之后是否需要等待?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40427263/

10-13 08:06