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_message
,print_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
。