【问题标题】:sysread returns undef, errno is EINVAL, but working?sysread 返回 undef,errno 是 EINVAL,但是工作吗?
【发布时间】:2014-08-01 09:30:16
【问题描述】:

我为系统事件文件的非阻塞输入设置了一些代码。

sysopen(FILE, $targetInput, O_NONBLOCK|O_RDONLY) or die "Failed to open $targetInput, quitting.\n";
binmode(FILE);


#More assignments and preparations here...

while (1) {

    #Code that justifies non-blocking I/O here...

    $rBytes = sysread(FILE, $buffer, 16);

    printf("%d vs %d\n", $!, EAGAIN);       
    print defined($rBytes) ? "Defined!\n" : "Undef!\n";


    if (!defined($rBytes) && $! == EAGAIN) {
        #Nothing actually read in non-blocking mode:
        usleep(1000);
    } else {
        #Got an event, moving on:
        print "Got it!\n";
        print "$rBytes!\n";
        last;
    }

}

#Logic using $buffer here...

这是一个非常标准的设置,有几十个例子可以用于这个东西。但是,我发现 100% 的时间,$rBytes 仍未定义,$! 设置为代码 22,EINVAL(无效参数)。已经进行了大量测试,以确保是 sysread 函数专门导致了这种情况,而在此之前绝对没有。

关键是,它有效。如您所见,我的代码假定任何 not 组合的 $rBytes 未定义(始终为真) $!EAGAIN(始终为假)只是假设一切都很好,因为我没有添加任何错误处理。这个代码块后面是一个巨大的开关/案例;不存在的数据“无害地”通过它,循环返回以尽可能快地再次执行。

当接收到有效输入时,$rBytes仍然未定义。但是由于$! 仍然不是EAGAIN,它也传递给程序的其余部分并按预期准确运行,$buffer 包含它应该包含的内容。如果我不看一下我的 CPU 使用率计,我实际上根本不会注意到这个问题,如果它是一个快速的一次性脚本,我可能不会尝试修复它。

我可以肯定地说,“无效论点”的指控是虚假的。问题是,为什么它会给出那个错误代码,为什么$rBytes总是未定义?

【问题讨论】:

  • 你在调用print之后检查$!,而不是在调用sysread之后...
  • @ikegami 那里,已修复。我显然已经尝试过其他任何挑剔的东西吗?
  • 这不是吹毛求疵。 print 定期将 $! 设置为成功。 ($! 对成功毫无意义。)如果你想要一个傻瓜,那么我会指出你只修复了$! 的一个用途。
  • 所以你是说sysread 也返回$! == 22?如果是这样,下一步是提供执行的strace
  • Re “我已经给出了必要的东西,而不是发布 574 行几乎没有问题的代码。”你不应该给出 574 行代码,而且你没有给出必要的东西。请提供您知道会出现问题的代码。

标签: perl file-io


【解决方案1】:

当我正在拼凑一个快速脚本来模拟迄今为止所做的假设时,我实际上自己偶然发现了答案;果然,所有必要的信息一直都在问题中。

典型的系统事件文件处理长度为 24 字节的消息。当然,这段代码试图从这些事件中提取 16 位时间戳,并将其余部分留待以后使用。由于我自己不理解的原因,sysread 不喜欢那样。

通过确保所需的长度大于或等于 24,sysread 将报告已读取的字节数和$! 记录的内容。 24 可能是一个幻数,或者它可能只是在从非阻塞资源中读取部分消息时出现问题(在阻塞模式下不会发生错误)。它仍在将适当的数据放入$buffer,大概是因为底层代码通过引用传递它并且在发生错误时不会将其归零,这就是显示块之后的一切正常的原因。

【讨论】:

  • “典型的系统事件文件处理长度为 24 字节的消息。” ——这听起来像是必要的信息,而这些信息一直都不是问题。显示$targetInput 的值可能会有所帮助。 (我什至不确定“系统事件文件”是什么,快速的 Google 搜索也没有发现。)
  • 我也想知道您所说的“典型的系统事件文件适用于长度为 24 字节的消息。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-13
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
相关资源
最近更新 更多