【问题标题】:How to check if a process has been finished?如何检查一个进程是否已经完成?
【发布时间】:2021-07-13 06:13:10
【问题描述】:

这是我用来检查子进程是否已在 C/cC++ 语言中完成的方式:

waitpid(job.pid,&tmp,WNOHANG)>=0;

但经过一番阅读,我认为这是错误的,因为我是在询问 waitpid 是否成功完成,而不是询问进程是否完成。

我该如何解决这个问题?

【问题讨论】:

  • 正如所写,它是一个不直接分配给任何东西的表达式(tmp 被分配给作为对 waitpid() 的调用的副作用,如果它检测到一个退​​出的进程) .作为if 条件的一部分,它可能很有用。也许你应该使用pid_t corpse = waitpid(…);WNOHANG 意味着你经常会收到一个错误 (-1) 返回,errno 将被设置为 EAGAIN(这意味着你可能会在未来的电话中成功,大致 - 你会得到 ECHILD 如果孩子已经死了,并且已经被等待)。
  • 这个函数的奇怪之处是一个很好的理由将它包装在一个你在项目中重用的函数中。仔细阅读手册页并写一次正确的内容将为您省去很多麻烦。
  • @EmanuelP 这就是我要寻求帮助的,为什么我应该将结果保存在变量中?结果意味着 waitpid 是否工作,而不是进程是否完成或仍在运行
  • @JonathanLeffler 你能告诉我它的样子吗,我还是很困惑

标签: c linux unix process


【解决方案1】:

当这样调用时,waitpid 可以返回三个东西

  • 0:状态不可用。这意味着该进程仍在运行。
  • -1:错误。 errno 应该被检查。可以是EINTR,在这种情况下,您应该再次尝试调用waitpid。它也可以是ECHILD,在这种情况下,您要么已经确定进程已提前结束,要么它是无效/不相关的 pid。如果发生这种情况,则说明您的程序逻辑有问题。
  • 您要求的 pid。在这种情况下,该过程结束。 如何结束,您可以使用第二个参数中返回的值进行检查,tmp 在您的情况下。手册页中解释了有关此值的各种宏。

因此,无需关心进程退出状态,您可以像这样检查它:

bool isdone(pid_t pid)
{
    int status;
    while((pid_t r = waitpid(pid, &status, WNOHANG) != pid)
    {
        if(r == 0) return false;
        if(errno == EINTR) continue;
        // handle errors
    }
    return true;
}

【讨论】:

  • 在某些情况下,返回-1并将errno设置为ECHILD是正常的,并不意味着存在逻辑错误。
  • @zwol 你能澄清一下吗?在什么情况下会发生这种情况?
  • 我想到的例子是,如果你在收到 SIGCHLD 后循环 waitpid(-1, &status, WNOHANG)。然后接收 either 一个 0 返回值, 一个带有 errno 设置为 ECHILD 的 -1 返回值,仅仅意味着没有更多的状态要报告,循环应该结束.
猜你喜欢
  • 2020-08-28
  • 1970-01-01
  • 2021-07-28
  • 2021-11-08
  • 2011-02-12
  • 2021-11-15
  • 1970-01-01
  • 2017-11-13
  • 2019-05-24
相关资源
最近更新 更多