如何确保使用 TerminateProcess WinAPI 发出终止信号的进程实际上已终止?

问题描述 投票:0回答:1

我正在编写以下代码来终止具有给定 PID 的进程:

int TerminateProcessInstance(DWORD dwPID)
{
 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
 if (!TerminateProcess(hProcess, 0))
 {
  cout << "Failed to initiate terminate process" << endl;
  return -1;
 }
 else
 {
  // Now that the termination of process is initiated,
  // how do I confirm the process is terminated before proceeding here
 }
 CloseHandle(hProcess);
 return 0;
}

TerminateProcess API 文档提到使用 WaitForSingleObject 来确保进程已终止:

TerminateProcess 是异步的;它启动终止并立即返回。如果您需要确保进程已终止,请使用进程句柄调用 WaitForSingleObject 函数。


我应该像这样更新代码吗?

int TerminateProcessInstance(DWORD dwPID)
{
 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
 if (!TerminateProcess(hProcess, 0))
 {
  cout << "Failed to initiate terminate process" << endl;
  return -1;
 }
 else
 {
  bool bStatus = WaitForSingleObject(hProcess, 60000);
  if(bStatus == WAIT_TIMEOUT)
  {
   cout << "Failed to terminate process" << endl;
   return -1;
  }
 }
 CloseHandle(hProcess);
 return 0;
}

我的另一个问题是,如果在我调用 WaitForSingleObject 之前 TerminateProcess 确实成功终止了进程,那么句柄 hProcess 的状态将是什么?

这种情况下 WaitForSingleObject 会失败吗?

c++ windows winapi terminate waitforsingleobject
1个回答
0
投票

在进程句柄上调用(对象)wait 函数 是一项定义明确的操作,可以确定进程是否已终止。

这是易于遵循的建议。为了理解为什么这是真的,我们需要涵盖几个概念并在此过程中引入支持术语。


从根本上来说,进程是一个保存资源的容器。代表进程的object是数据。数据不执行。

执行单元是线程。每个线程都属于一个进程。当我们通俗地说“进程执行”时,我们的意思是“进程拥有的一个或多个线程有资格运行。”

在我们查看进程终止之前,这似乎不是一个有用的区别。对

TerminateProcess
的调用会遍历进程对象中存储的所有线程,并依次终止每个线程。进程对象本身保持活动状态。


随着核心原语的粗略描述,上一段留下了一个问题:如果

TerminateProcess
不销毁进程对象,谁会销毁,何时销毁?

(内核)对象生命周期由 对象管理器负责。它维护每个对象的引用计数,在将

HANDLE
分发给客户端时递增它,并在客户端通过调用
CloseHandle
放弃其(共享)所有权时递减它。

引用的对象仅在其最终的

HANDLE
被释放后才会被销毁。因此,对
OpenProcess
的成功调用至少会使进程对象保持活动状态,直到
HANDLE
被传递到
CloseHandle
中为止。


最后一部分围绕同步 API。每当对象收到信号或超时到期(以先发生者为准)时,等待函数(例如

WaitForSingleObject
)就会返回。当进程出于自由意志或强制终止时,进程对象会转换到(并保持)有信号状态。


总结:

  • 成功调用
    OpenProcess
    可以让您控制流程对象的生命周期
  • TerminateProcess
    不会破坏进程对象
  • 等待函数可以可靠地等待有效进程句柄上的进程终止

由于以下几个原因,建议的代码仍然是错误的:

  • 它请求的权限 (
    PROCESS_ALL_ACCESS
    ) 比它需要的 (
    PROCESS_TERMINATE | SYNCHRONIZE
    )
  • 调用时不会检查错误
    OpenProcess
  • 它将
    WaitForSingleObject
    的返回值强制转换为
    bool
  • 它会在几个错误退出时泄漏进程
    HANDLE

更好的实现应该是这样的:

int TerminateProcessInstance(DWORD dwPID) {
    HANDLE hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, dwPID);
    if (hProcess == NULL) return -1;

    if (!TerminateProcess(hProcess, 0)) {
        cout << "Failed to initiate terminate process" << endl;
        CloseHandle(hProcess);
        return -1;
    }

    DWORD res = WaitForSingleObject(hProcess, 60000);
    if(res != WAIT_OBJECT_0) {
        cout << "Process didn't terminate within timeout" << endl;
        CloseHandle(hProcess);
        return -1;
    }

    CloseHandle(hProcess);
    return 0;
}

使用 Windows 实现库 将使此代码更短、更具可读性、可维护性和健壮性。

© www.soinside.com 2019 - 2024. All rights reserved.