$! 只有在系统调用指示它设置了$! 后才有意义。
问题:
- 在使用系统调用之前不要检查是否设置了
$!。
- 在你感兴趣的系统调用和
$!的使用之间调用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。)