windows – 在TerminateProcess(GetCurrentProcess(),exit_code)之后需要等待吗?

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来终止你自己的进程同样是残酷的.除了一个例外,它是最后的手段,即使在这种情况下,也是一个非常绝望的手段.任何执行此操作的人必须遇到比调用可能返回的问题更多的问题,否则他们肯定会调用ExitProcess,它显然不会返回(但可能会使进程陷入死锁).

通过TerminateProcess自终止引入了一个被终止的线程之一是当前线程的情况.终止后的APC处理没有为它激活:在Windows 7内核中,请参阅PspTerminateThreadByPointer,这再次使得当前线程的用户模式终止转到非返回的PspExitThread而不是为APC排队的特殊情况.最后退出.

所以,我的读法是带有-1作为句柄的TerminateProcess不会返回,但是如果你在内核中执行最后一个为调用线程执行的指令,你可能会发现进程中的其他线程仍然可以执行处理APC但是你的APC队列已经耗尽并且即将被切断,永远不会回来.实际上,如果此时您的线程以某种方式处理APC,则内核错误检查!

顺便说一句,TerminateProcess的例外是残酷的,它实际上是NTDLL最后做的事情,即使是通过ExitProcess进行相对温和的自我终止.它肯定是众所周知的,但总是让我感到惊讶的是,要处理RtlExitUserProcess,NTDLL会调用两次NtTerminateProcess.首先,进行用户模式清理并调用NtTerminateProcess,将NULL作为句柄.如果成功,则会有更多用户模式清理,最后调用NtTerminateProcess,将-1作为句柄.

好吧,最后一次调用就是你从TerminateProcess得到的,带有-1作为句柄.当你通过TerminateProcess自行终止时,你只是在用户模式和内核模式中跳过了从ExitProcess获得的清理.无论如何,当TerminateProcess实际上是由NTDLL作为ExitProcess的结束时,显然它不会返回.

点赞