【问题标题】:stat(2) and EINTRstat(2) 和 EINTR
【发布时间】:2019-12-06 01:38:44
【问题描述】:

根据 POSIX,有一些系统调用支持的 i/o 函数(我最近发现至少两个:stat()mkdir(),但几乎可以肯定还有更多)在可能的 errno 值中没有 EINTR,但肯定会因为磁盘繁忙或网络挂载的文件系统而阻塞。

我怀疑可能存在从这些函数返回 EINTR 的稍微不符合 POSIX 的实现,尤其是在网络文件系统上。那可能性有多大?是否有必要检查 stat() 的 EINTR 或者我可以绝对确定这个系统调用不会被中断?

更新 如回答和评论中所述,POSIX 2.3 允许:

如果且仅当所有这些错误条件始终可以与本卷 POSIX.1-2017 中描述的错误条件相同的情况下,实施可能会在此处列出的错误编号。对于本卷 POSIX.1-2017 中描述的错误情况,实施不应生成与本卷 POSIX.1-2017 所要求的错误编号不同的错误编号,但可能会产生额外的错误,除非针对特定功能明确禁止。

但是有一件重要的事情:EINTR 实际上不是 error 条件(从任何角度来看它都不是失败),并且它的正确处理总是需要一些特殊的代码.

举例说明我的意思:假设stat() 从 NFS 处理程序返回 POSIX 未记录的 ECONNRESET。这个错误代码没有记录,但它不会造成任何伤害:我们知道系统调用由于某种原因失败了,我们的错误处理程序可能不关心发生了什么确切的错误,因为所有这些都意味着失败。 EINTR 完全不同。

【问题讨论】:

  • 即使他们这样做了,我也不认为这违反了 POSIX 合规性。 POSIX 2.3 说:“当且仅当所有这些错误条件始终可以与本卷 POSIX.1-2017 中描述的错误条件相同的情况下,实现可能会在此处列出的错误编号。”从stat()返回的EINTR应该是真的,意味着有信号中断了调用,你可以再试一次。

标签: c unix posix


【解决方案1】:

POSIX.1-2017 的“系统接口:一般信息”部分中Error Numbers 的第2.3 节中,您可以找到:

实现可能支持未包含在此列表中的其他错误,可能会在此处描述之外的情况下生成此列表中包含的错误,或者可能包含防止某些错误发生的扩展或限制。

每个参考页面上的 ERRORS 部分指定了所有实现应检测到哪些错误条件(“将失败”),以及可以选择由实现检测哪些错误条件(“可能失败” )。如果未检测到错误条件,则请求的操作应成功。如果检测到错误情况,则请求的操作可能已部分执行,除非另有说明。

如果且仅当所有这些错误条件始终可以与本卷 POSIX.1-2017 中描述的错误条件相同的情况下,实施可能会在此处列出的错误编号。对于本卷 POSIX.1-2017 中描述的错误情况,实施不应生成与本卷 POSIX.1-2017 所要求的错误编号不同的错误编号,但可能会产生额外的错误,除非针对特定功能明确禁止。

每个实现都应在一致性文档中记录检测到 POSIX.1-2017 中定义的每个可选条件的情况。一致性文档还可能包含未检测到一个或多个可选错误条件的声明。

在我看来,引用的第一个段落允许在您描述的情况下生成EINTR

【讨论】:

  • 这似乎是相关的,但我不完全确定。在问题中添加了更多文本。
  • 对“不是错误条件”的有趣解释。从我的角度来看,EINTR 确实表示一个错误——在系统调用完成之前发生了中断,所以系统调用没有完成它被要求做的事情,所以这是一个错误情况。中断后事物处于什么状态并不一定很清楚。但是,未完成的 I/O 操作要么返回读取或写入数据的简短计数,要么返回错误并将 errno 设置为 EINTR(如果没有完成 I/O)。有一些可重新启动的系统调用。
【解决方案2】:

如果我们以 Linux NFS 为例:NFS doesn't claim full POSIX compliance.

此外,默认选项最接近您通过 NFS 获得的 POSIX 合规性,尤其是您不会获得 EINTR

但是,如果您使用某些选项进行安装,例如softtimeoretransintr,那么您正在主动要求文件系统将行为更改为可能不符合 POSIX 的行为。

【讨论】:

    【解决方案3】:

    stat 不是“系统调用”;它是一个系统界面;即标准库函数。它的实现可能涉及系统调用,但它当然不必;它可能只使用其他系统接口来实现,无论是否记录在案。

    它肯定会阻塞。但这并不意味着调用stat 时被阻塞的进程会唤醒并返回请求文件统计信息以外的其他内容,因为它被发送了一个中断。并且实现也不会因为作为系统接口而束手无策。如果实现涉及对返回EINTR 的其他阻塞系统接口的调用,则stat 实现要做的正确事情是重试任何被中断的调用。没有什么能阻止它这样做。

    如果要在 errno 设置为 EINTR 的情况下返回失败,那肯定会违反 Posix(恕我直言),但我肯定不会冒险使用标有“所有 unices 都是完美无缺”。如果你想在失败后检查EINTR,以防本地操作系统不是完美的posix,我当然不会批评你。但实际上我认为这不太可能。

    【讨论】:

      猜你喜欢
      • 2012-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 2021-10-31
      • 1970-01-01
      • 2018-04-16
      相关资源
      最近更新 更多