【问题标题】:Can dup2 really return EINTR?dup2 真的可以返回 EINTR 吗?
【发布时间】:2013-04-02 12:57:54
【问题描述】:

在规范和两个实现中:

  • 根据 POSIX,dup2() 可能会返回 EINTR。
  • Linux 手册页将其列为允许。
  • FreeBSD 手册页表明它从未返回。这是一个错误吗 - 因为它的紧密实现可以 EINTR(至少对于 TCP 徘徊,如果没有别的)。

实际上,Linux 可以为dup2() 返回 EINTR 吗?如果是这样,那可能是因为close() 决定等待并且信号到达(TCP 逗留或在关闭时尝试同步的狡猾的文件系统驱动程序)。

实际上,FreeBSD 是否保证不为dup2() 返回 EINTR?在这种情况下,它一定是它不会费心等待旧 fd 上的任何未完成操作,而是简单地取消链接 fd。

POSIX dup2() 指的是“关闭”(不是斜体),而不是引用实际的 close() 函数时是什么意思 - 我们是否理解它只是在以一种非正式的方式“关闭”它(取消链接文件描述符),还是试图说效果应该就像首先调用 close() 函数然后自动调用 dup2() 一样。

如果 fildes2 已经是一个有效的打开文件描述符,它应该首先被关闭,除非 fildes 等于 fildes2 在这种情况下 dup2() 将返回 fildes2 而不关闭它。

如果dup2() 确实必须关闭,等待,然后自动复制,这将是实现者的噩梦!这比 close() 惨败的 EINTR 要糟糕得多。懦弱的 POSIX 甚至没有说是否在 EINTR 的情况下发生了重复......

【问题讨论】:

  • 在 Linux 中 dup2 是原子的。
  • 谢谢。关键是,如果dup2() 执行与close() 相同的等待,这可能很难实现。 close() 实现取消链接 fd 表中的条目,然后等待剩余的文件结构。如果它被中断,则 fd 将关闭。如果 dup2 实现必须等待,它怎么可能是原子的 - 显然它不能在那个时候锁定 fd 表,所以你会陷入 EMFILE 和 EINTR 错误都发生的混乱......跨度>
  • 库文档说操作不能被中断,并且它没有将 EINTR 列为可能的错误。大概它的实现方式与close不同。
  • 如果您收到EINTR,您可以重试dup2 呼叫。所以在某些方面它不是一场灾难......
  • @teppic: atomic 在这里不是问题。 atomic 的意思是:要么成功,要么失败。它可能会失败。如果它确实失败了,也没有造成任何伤害。 (例如:关闭文件,但不复制新的 fd)

标签: linux posix freebsd language-lawyer file-descriptor


【解决方案1】:

以下是 C/POSIX 库文档中关于标准 Linux 实现的相关信息:

 If OLD and NEW are different numbers, and OLD is a valid
 descriptor number, then `dup2' is equivalent to:

      close (NEW);
      fcntl (OLD, F_DUPFD, NEW)

 However, `dup2' does this atomically; there is no instant in the
 middle of calling `dup2' at which NEW is closed and not yet a
 duplicate of OLD.

它将dupdup2 返回的可能错误值列为EBADFEINVALEMFILE,没有其他值。该文档指出,所有可以返回 EINTR 的函数都按此列出,这表明这些函数没有。请注意,这些是通过fcntl 实现的,而不是对close 的调用。

【讨论】:

  • 我的 linux 手册页确实将 EINTR 列为可能的错误返回。
  • @wildplasser - 这是来自图书馆文档本身;手册页并不总是正确的。
  • 那么这里的文档中有错误。如果dup2() 真的等价于close() 后跟fcntl(),那么如果close() 返回EINTR 会发生什么?我真的怀疑这些文档中存在错误,但我们必须检查内核源才能找出答案。看到dup2 等待 TCP 停留和原子化所需要的后空翻,我会感到惊讶。
  • @NicholasWilson - 不一定。它说等价,但并没有说它是一样的。可能存在错误,但我认为这不太可能,因为文档在返回值上的明确程度。
  • OpenSuse 12.3 for dup2 列出了 2 个手册页 (2) 和 (3p)。两者都将 EINTR 显示为可能的错误 - 原因:调用被信号中断;见信号(7)。 3p 是 POSIX @teppic - 那么你在上面的答案中引用了什么? -- 请提供网址。
【解决方案2】:

8 年后,这似乎仍然没有记录。 我查看了 linux 源代码,我的结论是 dup2 在当前版本的 Linux 中不能返回 EINTR

特别是,fs/file.c 中的函数do_dup2 忽略了filp_close 的返回值,这可能导致close 在某些情况下返回EINTR(参见fs/open.cfs/file.c) .

dup2 的工作方式是它首先更新原子文件描述符,然后等待需要在关闭时发生的任何刷新。刷新时发生的任何错误都会被忽略。

【讨论】:

    猜你喜欢
    • 2022-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多