使用 Window CRT 检测生成进程的死亡

发布于 2024-08-19 01:37:42 字数 726 浏览 13 评论 0原文

执行摘要:我需要一种方法来确定我通过 _spawnl 生成并使用 _pipe 中的 FD 进行通信的 Windows 进程是否已终止。

详细信息:

我使用 Windows 中的低级 CRT 函数(_eof、_read)与通过调用 _spawnl(带有 P_NOWAIT)标志而生成的进程进行通信。我使用 _pipe 创建文件描述符来与这个生成的进程进行通信,并在命令行上将这些描述符(FD #)传递给它。

值得一提的是,我不控制生成的过程。对我来说这是一个黑匣子。

事实证明,我们生成的进程偶尔会崩溃。我试图通过检测崩溃来使我的代码对此具有鲁棒性。不幸的是,我看不到一种方法来做到这一点。在我看来,如果进程已终止,对这些描述符之一的 _eof 或 _read 调用将返回错误状态 (-1),这似乎是合理的。

不幸的是,事实并非如此。看起来描述符有自己的生命周期,独立于生成的进程。因此,即使另一端的进程已死亡,我在用于与其通信的文件描述符上也没有收到错误状态。

我已经获得了嵌套进程的 PID(从 _spanwnl 调用返回),但我看不到可以用它做任何事情。除了一件事之外,我的代码运行得非常好。我无法检测生成的进程是只是忙于计算答案还是已经死亡。

如果我可以使用 _pipe 和 _spawnl 中的信息来确定生成的进程是否已死亡,那我就很高兴了。

非常欢迎提出建议。

提前致谢。

更新:我找到了一个相当简单的解决方案并将其添加为所选答案。

Executive summary: I need a way to determine whether a Windows process I've spawned via _spawnl and am communicating with using FDs from _pipe has died.

Details:

I'm using the low-level CRT function in Windows (_eof, _read) to communicate with a process that was spawned via a call to _spawnl (with the P_NOWAIT) flag. I'm using _pipe to create file descriptors to communicate with this spawned process and passing those descriptors (the FD #) to it on the command line.

It is worth mentioning that I don't control the spawned process. It's a black box to me.

It turns out that the process we are spawning occasionally crashes. I'm trying to make my code robust to this by detecting the crash. Unfortunately, I can't see a way to do this. It seems reasonable to me to expect that a call to _eof or _read on one of those descriptors would return an error status (-1) if the process had died.

Unfortunately, that isn't the case. It appears that the descriptors have a life of their own independent of the spawned process. So even though the process on the other end is dead, I get no error status on the file descriptor I'm using to communicate with it.

I've got the PID for the nested process (returned from the _spanwnl call) but I don't see anything I can do with that. My code works really well except for one thing. I can't detect whether the spawned process is simply busy computing me an answer or has died.

If I can use the information from _pipe and _spawnl to determine if the spawned process is dead, I'll be golden.

Suggestions very welcome.

Thanks in advance.

UPDATE: I found a fairly simple solution and added it as the selected answer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦太阳 2024-08-26 01:37:42


如何了解子进程状态和资源使用情况windows?

你可以在从spawnl返回的句柄上使用WaitForSingleObject;它对我来说工作得很好。听起来你可能已经尝试过这个,但也许我误解了你的回答。

生成进程并等待其完成而不使用 _P_WAIT 的示例代码:

HANDLE hProcess = (HANDLE) _spawnl(_P_NOWAIT, "slave.exe", "slave.exe", NULL);
while(1)
{
  Sleep(100);
  if (WaitForSingleObject(hProcess, 0) == WAIT_OBJECT_0)
  {
    break;
  }
}

See
How to know child process status and resource usage on windows?

You can just use WaitForSingleObject on the handle returned from spawnl; it's working fine for me. It sounds like you might have already tried this, but maybe I'm misunderstanding your responses.

Sample code that spawns a process and waits for it to finish without using _P_WAIT:

HANDLE hProcess = (HANDLE) _spawnl(_P_NOWAIT, "slave.exe", "slave.exe", NULL);
while(1)
{
  Sleep(100);
  if (WaitForSingleObject(hProcess, 0) == WAIT_OBJECT_0)
  {
    break;
  }
}
攒一口袋星星 2024-08-26 01:37:42

如果您希望能够检测到进程已退出,则必须向食物链上游移动。本机 CreateProcess() Win32 API 可以返回一个 HANDLE,您可以在 WaitForSingleObject() API 中使用它来等待或测试进程是否已退出。如果你能得到PID,你就可以使用OpenProcess()来得到你需要的HANDLE。

另一种方法是使用 _P_WAIT 使其成为同步调用。这将需要一个线程。

You'll have to move up the food chain if you want to be able to detect that the process exited. The native CreateProcess() Win32 API can give you back a HANDLE, you can use it in the WaitForSingleObject() API to wait or test if the process has exited. If you can get the PID, you can use OpenProcess() to get the HANDLE you need.

Another approach is to use _P_WAIT to make it a synchronous call. That will require a thread.

给不了的爱 2024-08-26 01:37:42

感谢 nobugz 提供了很多好的建议。我最终没有采取他的“向食物链上游移动”的路线,所以我把这个写成一个单独的答案,但这很大程度上是他反馈的结果。

我使用了现有的对spawnl 的调用。事实证明这是可能的,因为当使用 P_NOWAIT 模式调用时,返回值实际上与 OpenProcess 相同。这很令人困惑,因为spawnl 的返回类型为intptr_t,而OpenProcess 的返回类型为HANDLE。但它们是等效的(至少根据我的测试)。

知道这一点后,我仍然没有摆脱困境。我需要一种可靠的方法来确定该进程是否仍在运行。即使进程已终止,我使用进程句柄(例如 GetModuleBaseName)进行的所有各种调用都会成功。

最终,我求助于调用 GetProcessId(使用我的进程句柄)来获取进程 ID,然后调用 EnumerateProcesses 并挖掘从它返回的结果,以查看是否有任何正在运行的进程共享相同的进程 ID。

我承认使用更高级别的 API(如 nobugz 所建议的)可能是一般的方法。就我而言,我已经让所有代码正常工作,只需要确定嵌套进程是否仍在运行,因此我采取了极简主义方法。

再次感谢 nobugz 提供的所有有用的建议。

Thanks to nobugz for lots of good advice. I didn't end up taking his route of "moving up the food chain" so I'm writing this up as a separate answer but it is very much the result of his feedback.

I used my existing call to spawnl. It turns out this was possible because when called with the P_NOWAIT mode the return value is actually the same as OpenProcess. This is confusing because spawnl has a return type of intptr_t whereas OpenProcess has a return type of HANDLE. But they are equivalent (at least based on my testing).

Knowing this, I still wasn't out of the woods. I needed a reliable way to determine if the process was still running. All the various calls I made using the process handle (e.g. GetModuleBaseName) succeeded even when the process was dead.

Ultimately, I resorted to calling GetProcessId (with my process handle) to get the process ID and then calling EnumerateProcesses and digging through the results returned from it to see if any of those running processes shared the same process ID.

I would acknowledge that using higher level APIs (as nobugz suggested) is probably the way to go in general. In my case, I already had all the code working and only needed to determine if the nested process was still running so I took a minimalist approach.

Thanks again to nobugz for all the helpful suggestions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文