来自 pidfd 的 epoll() 之后 waitpid() 的保证

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

我正在编写一个进程管理器,用于监视其子进程并在必要时重新启动它们。

目前,我有

pidfd
与每个正在运行的进程相关联,并且
epoll
正在等待所有这些
pidfd
。当一个进程终止时,
epoll_wait()
被唤醒,为了确定进程的退出代码,我使用阻塞
waitpid()
来确定我的进程`退出代码(在我的程序中,需要确定是否重新启动进程或不是)。

我想知道我的解决方案是否存在任何潜在问题,因为我必须使我的流程管理器尽可能无锁且安全。我主要关心的是在

waitpid()
变得可读后使用
pidfd
。有没有可能这个等待会锁定我的执行?

如果您能就我的问题提供任何帮助、见解或反馈,我将不胜感激。

linux unix posix epoll waitpid
1个回答
0
投票

总的来说,你的做法是正确的。

以下情况可能会导致故障:

  1. 程序中的另一个线程正在调用
    wait
    /
    waitpid
    ,并在 epoll 响应式
    waitpid
    调用运行之前“窃取”给定子进程的收获。如果您的代码是一个独立的程序,并且您可以确定不存在这样的线程,那么您可能是安全的。在一些严重面向事件循环的运行时(nodejs和Python中的uvloop,Python的
    Popen
    multiprocessing
    )中可能存在这样的收割者线程。如果您正在使用这些运行时之一,请小心。
  2. 程序中存在
  3. SIGCHLD
    信号处理程序,它会自动调用
    wait
    /
    waitpid
    来响应接收到的信号。这与上面的线程情况类似,但通过不同的机制。许多高级编程语言的运行时(例如 Python、Go)都会安装这样的处理程序。如果您的运行时这样做,它可能还提供了一种取消设置或禁用此行为的方法;如果是的话,请检查文档。
    您的程序已将
  4. SIGCHLD
     处理设置为 
    SIG_DFL
    ,其中 
    sigaction
    SIG_IGN
    ,或者设置了 
    sigaction
    SIG_NOCLDWAIT
    。这些条件启用了
    “自动收割”子进程。在此模式下,wait
    waitpid
    不是必需的,调用它们将始终阻塞。这在野外比较罕见。
如果您的程序是独立的,并且没有作为库分发或与其他任意代码集成,那么您的方法是合适的,前提是您验证您的语言/运行时没有做任何顽皮的事情。

如果您的程序与其他任意代码集成,那么按照 Shawn 在评论中建议的方式进行操作可能是有意义的,并且通过设置

waitpid

 标志来完成对 
WNOHANG
 的 epoll 响应式调用。这样,如果 
waitpid
 的结果表明其他东西已经收割了子进程,您可以报告错误或警告,而不是停止整个流程管理器。这就是 Python 中的 
PidfdChildWatcher
 所做的事情
,因为很难保证 Python 中的程序不会造成上面列出的任何情况。

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