【问题标题】:Child process is able to change parent epoll state子进程能够更改父 epoll 状态
【发布时间】:2014-02-23 20:50:54
【问题描述】:

我试图弄清楚为什么子进程能够更改父 epoll 状态。

我有程序声明一个静态 epoll 对象(一个包装 epoll 的对象):

static EventManager* evMgrPtr = NULL;

父进程初始化它并用它来监听一个监听套接字(父进程基本上是一个守护进程,偶尔需要通过监听套接字接受这些请求来响应健康检查请求)。

孩子们做了完全不同的事情,但是,程序不做 fork/exec,而是孩子们在同一个翻译单元中继续并运行一段代码。

      pid_t pid = fork();
      switch(pid) {
      case -1:
        YREPL_LOG_FATAL("Couldn't start server process ");
        exit(EXIT_OK);

      case 0:
    #ifndef __FreeBSD__ 
        assert( closeThisFd != -1 );
        evMgr.unregisterSocketEvent( closeThisFd );
        close( closeThisFd );
    #endif
        close(outpipe[0]);
        close(errpipe[0]);
        dup2(outpipe[1], 1);
        dup2(errpipe[1], 2);
        close(outpipe[1]);
        close(errpipe[1]);

问题是我在子进程中执行 evMgrPtr->unregisterSocketEvent( closeThisFd ) 后,我发现父进程也停止监视监听套接字了!!!

谁能解释一下为什么会这样。我认为一旦执行叉子,父母和孩子就会做牛。因此,无论子代对其 epoll 对象的副本所做的任何事情都不应反映在父代中,对吧?

【问题讨论】:

  • 文件描述符在整个继承进程空间中是唯一的。如果您想独立处理子进程,请参考dup()
  • 我不认为我想 dup() 继承的 fd。我要做的就是让父级继续监听端口,同时阻止任何后续分叉的子级监听端口。

标签: c++ linux epoll


【解决方案1】:

您似乎使用了基于 EPOLL 的事件循环。因此,由于 epoll-object 本身的文件描述符在子进程和父进程之间共享,因此从子进程中基于 epoll() 的描述符中删除文件描述符也会影响父进程:)。请阅读 man epoll, man epoll_create。

【讨论】:

  • 从代码片段中可以看出,该代码是从 FreeBSD 移植到 RHEL 的。在 FreeBSD 实现中,它使用 kqueue 显然不会像手册页所建议的那样跨 fork 共享队列。 RHEL 是否存在类似的事件机制?哪个事件队列没有在父/子之间共享?
  • 根据 epoll 手册页。 “每当通过 dup(2)、dup2(2)、fcntl(2) F_DUPFD 或 fork(2) 复制描述符时,就会创建一个引用相同打开文件描述的新文件描述符。打开文件描述继续存在直到所有引用它的文件描述符都已关闭。只有在引用底层打开文件描述的所有文件描述符都已关闭之后(或者如果使用 epoll_ctl() 显式删除描述符,则在此之前从 epoll 集中删除文件描述符)。”
猜你喜欢
  • 2016-10-02
  • 1970-01-01
  • 2018-07-08
  • 2023-03-19
  • 2019-07-12
  • 2021-03-31
  • 2019-12-23
  • 1970-01-01
  • 2021-01-12
相关资源
最近更新 更多