【问题标题】:How to asynchronously wait for process termination and find out the exit code?如何异步等待进程终止并找出退出代码?
【发布时间】:2021-09-23 15:47:51
【问题描述】:

pidfd_open 和 poll 的等待效果很好。

我面临的问题是,在进程退出后,poll() API 显然删除了有关现在已死进程的信息,因此带有P_PIDFD 参数的waitid 立即失败,代码22“无效参数”

我认为我无法为每个子进程启动一个线程以在阻塞 waitpid 上休眠,我有多个进程,还有另一个句柄不是我需要有效轮询的进程。

有什么解决方法吗?

如果重要的话,我只需要支持在 ARM64 和 ARMv7 CPU 上运行的 Linux 5.13.12 和更新版本。

内核调用的大致顺序如下:

  1. fork
  2. 在孩子:setresuid,setresgid,execvpe
  3. 在新的孩子:printf,sleep,_exit
  4. 同时在父级中:pidfd_open、poll,一旦完成waitid 和P_PIDFD 第一个参数。

预期结果:waitid 应该给我孩子的退出代码。

实际结果:它什么都不做,将errno设置为EINVAL

【问题讨论】:

  • 什么有效?什么不起作用?请发布minimal reproducible example。顺便说一句,您可以将 -1 传递给 waitpid,因此您只需要一个。
  • 你能否创建一个线程安全变量(即布尔标志,例如`bool sf_running = true;)在适当的时候将其设置为false,并在你的监控线程中测试它?
  • @n.1.8e9-where's-my-sharem。 poll 有效,当孩子退出时我会收到通知。 waitid 失败,所以我无法获取退出代码。
  • @ryyker 我在每个涉及的进程中只有一个线程。
  • waitpid 只有在你使用不正确的情况下才会失败。

标签: c linux asynchronous process embedded-linux


【解决方案1】:

有一个关键点。来自man waitid:

应用程序应指定至少一个标志 WEXITED、WSTOPPED 或 WCONTINUED 与选项参数进行或运算。

我路过是WNOHANG

而你想通过WNOHAND | WEXITED ;)

【讨论】:

  • 谢谢,它有效。大多。你知道如何阻止内核破坏我退出代码中 32 位中的 24 位吗?
  • 不是 libc 是操作系统内核,我正在使用这个 libc:git.musl-libc.org/cgit/musl/tree/src/process/waitid.c
  • 24 out of the 32 bits in my exit codes? 退出码有8位,我不明白。
  • _exit API 函数将 32 位整数作为参数。在siginfo_t 结构深处的si_status 字段也包含32 位数据。然而在这两者之间的某个地方,Linux 内核正在破坏我的整数,将它们截断为 8 位。
  • stackoverflow.com/questions/50982730/… 看起来 linux 在这里不兼容 POSIX 并且无论如何都是 8 位
【解决方案2】:

您可以使用单个收割线程,在waitpid(-1, &status, 0) 上循环。每当它获取一个子进程时,它会在当前子进程的集合中查找它,处理可能的通知(信号量或回调),并存储退出状态。

有一种值得注意的情况需要特别考虑:子进程可能在 fork() 返回父进程之前退出。这意味着收割者有可能在执行 fork() 的代码设法在任何数据结构中注册子进程 ID 之前看到子进程退出。因此, reaper 和 fork() 注册函数都必须准备好在数据存储中查找或创建记录,以跟踪子进程;包括调用回调或发布信号量。它一点也不复杂,但除非您习惯于以异步方式思考,否则很容易错过这些极端情况。

因为 wait(...)/waitpid(-1,...) 在没有要等待的子进程时立即返回(将 -1 和 errno 设置为 ECHILD),因此 reaper 线程可能应该等待当没有子进程等待时,在条件变量上使用在该条件变量上注册子进程 ID 信号的代码,以最大限度地减少无子进程情况下的资源使用。 (另外,请记住最小化 reaper 线程堆栈大小,因为默认情况下它过大(大约 8 MiB),并且浪费资源。我自己经常使用 2*PTHREAD_STACK_MIN。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-18
    • 1970-01-01
    • 2012-01-02
    • 2015-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多