套接字读取上的设备不合适


my $waitlist = IO::Select->new($self->{sock});
while($datalen < 9)
{
##timeout set as 50
if($waitlist->can_read($timeout || 0)) {
print_message(LOGLEVEL_TRACE, "INSIDE IF....", LOG_TAG);
$templen = $self->{sock}->sysread($tempdata, 9 - $datalen);
} else {
print_message(LOGLEVEL_TRACE, "INSIDE ELSE....", LOG_TAG);
print_message(LOGLEVEL_TRACE, "B4 ERROR $!", LOG_TAG);
$templen = 0;
$! = EWOULDBLOCK;
}

print_message(LOGLEVEL_TRACE, "ERROR $!", LOG_TAG);
}

在上面的代码中,"can_read"将错误作为设备的不合适 ioctl。想知道原因和修复需要做。

只有在系统调用指示它设置$!后,$!才有意义。

问题:

在使用系统调用集
  • 之前,不会检查系统调用集是否$!
  • 您在感兴趣的系统调用和使用$!之间调用print_messageprint_message肯定可以进行系统调用。

需要注意的一件事是检查can_read是否返回错误的方式真的很奇怪。

返回可供读取的句柄数组。TIMEOUT是在返回空列表($!保持不变)之前等待的最长时间,以秒为单位,可能是小数。如果未给出TIMEOUT并且注册了任何句柄,则调用将无限期阻止。出错时,将返回一个空列表,并设置$!以指示错误。若要区分超时和错误,请在调用此方法之前将$!设置为零,并在返回空列表后进行检查。

<小时 />

替换

my $waitlist = IO::Select->new($self->{sock});
while($datalen < 9)
{
##timeout set as 50
if($waitlist->can_read($timeout || 0)) {
print_message(LOGLEVEL_TRACE, "INSIDE IF....", LOG_TAG);
$templen = $self->{sock}->sysread($tempdata, 9 - $datalen);
} else {
print_message(LOGLEVEL_TRACE, "INSIDE ELSE....", LOG_TAG);
print_message(LOGLEVEL_TRACE, "B4 ERROR $!", LOG_TAG);
$templen = 0;
$! = EWOULDBLOCK;
}

print_message(LOGLEVEL_TRACE, "ERROR $!", LOG_TAG);
}

my $waitlist = IO::Select->new($self->{sock});
while (length($tempdata) < 9) {
$! = 0;
my @handles = $waitlist->can_read($timeout || 0);
if ($!) { # Yuck, just about anywhere else, this would be wrong.
print_message(LOGLEVEL_TRACE, "SELECT FAILED: $!", LOG_TAG);
...abort...
}
if (!@handles) {
print_message(LOGLEVEL_TRACE, "SELECT FAILED: Timeout", LOG_TAG);
...abort...
}
my $bytes_read = $self->{sock}->sysread($tempdata, 9 - $datalen, length($tempdata));
if (!defined($bytes_read)) {
print_message(LOGLEVEL_TRACE, "SYSREAD FAILED: $!", LOG_TAG);
...abort...
}
if (!$bytes_read) {
if (length($tempdata)) {
print_message(LOGLEVEL_TRACE, "SYSREAD FAILED: Premature EOF", LOG_TAG);
...abort...
}
# Reached EOF without reading anything.
last;
}
}

在您执行这些更改之前,我们不知道您是否遇到错误,更不用说它是什么了。

>评论:
  • 你错过了sysread的最后一个参数,这在这里是必要的。

  • 如果没有超时,像上面那样使用select是完全没用的(因为只有一个句柄)。sysread已经执行了必要的等待。

  • 如果有超时,则不是绝对超时。例如,假设您的超时为 5 秒,但您始终每 4 秒获得 1 个字节,则上述内容将运行 36 秒而不会超时。(好吧,这不是一个现实的例子,但只是因为我们只读取 9 个字节。对于绝对超时,您需要跟踪时间的流逝情况。(我会在前面使用my $wait_til = time() + timeout();,并在检查它是否为正数后$wait_til - time()传递给can_read

最新更新