sysread返回undef, errno为EINVAL,但工作



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

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 %dn", $!, 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函数引起的,而不是在它之前。

问题是,它有效。正如您所看到的,我的代码假设任何不是的东西,$rBytes的组合是未定义的(始终为真) $!EAGAIN(始终为假)只是假设一切都很好,因为我没有添加任何错误处理。这个代码块后面是一个巨大的开关/案例;不存在的数据会"无害地"跳过所有的数据,并以尽可能快的速度循环再做一次。

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

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

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

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

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

最新更新