gdb 的 MI 通过管道输出的级别触发 epoll_wait() 不会通知“(gdb)\n”行的存在

Level-triggered epoll_wait() on gdb's MI output through pipe doesn't notify the existence of the "(gdb)\n" line

在一个应用程序中,我生成 gdb 并将其 stdout(和其他)连接到管道。然后我 epoll_wait 在此管道(和其他管道)上收到 gdb 响应的通知。

每次 epoll_wait 以正 return 值醒来(有一个 fd 可以读取),我从 gdb 的 one 行中读取 stdout 管道(如果那是带有事件的 fd),然后返回 epoll_wait.

这一切工作正常,除了有时 gdb 响应的最后一行(总是 "(gdb)\n")未被读取,并且 epoll_wait returns 永远为 0。如果我等待几秒钟,然后从 gdb 的 stdout 管道读取,尽管 epoll_wait 是 returning 0,我可以收到 "(gdb)\n" 行。

这是怎么回事?该数据显然已在管道中准备好从中读取,但级别触发的 epoll 未为其生成事件。

一些注意事项:

我怀疑问题出在 C 标准库的缓冲上。这是我对事件时间表的猜测:

  • 你打电话给getline
  • getline 呼叫 read
  • 管道中有两条线可用,并且read returns它们都是
  • getline 给你第一行并缓冲第二行
  • 你打电话给epoll_wait
  • epoll_wait 块,因为内核发现管道中没有剩余数据
  • epoll_wait 几秒后超时
  • 您再次致电getline
  • getline 给你它之前缓冲的第二行

核心问题是,就内核而言,用户空间标准输入缓冲区中的数据与您已经读取和处理的数据没有区别。要解决此问题,切勿将 FD 提供给任何将其包装在 FILE * 中的函数,并直接使用 read 系统调用自行完成所有读取操作。