$! is only meaningful after a system call indicates it set $!.
Problems:
- You don't check if a system call set
$! before using it.
- You call
print_message between the system call in which you're interested and the use of $!, and print_message can surely make system calls.
One thing to note is the way of checking if can_read returned an error is really weird.
Return an array of handles that are ready for reading. TIMEOUT is the maximum amount of time to wait before returning an empty list (with $! unchanged), in seconds, possibly fractional. If TIMEOUT is not given and any handles are registered then the call will block indefinitely. Upon error, an empty list is returned, with $! set to indicate the error. To distinguish between timeout and error, set $! to zero before calling this method, and check it after an empty list is returned.
Replace
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);
}
with
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;
}
}
Until you perform these changes, we don't know if you got an error, much less what it is.
Comments:
You were missing the final argument for sysread, which is necessary here.
Using select as you did above is totally useless if there's no timeout (because there's only one handle). sysread will already perform the necessary waiting.
If there is a timeout, it's not an absolute timeout. For example, say you have a timeout of 5 seconds, but you consistently get 1 byte every 4 seconds, the above will run for 36 seconds without timing out. (Ok, that's not a realistic example, but only because we're only reading 9 bytes.) For an absolute timeout, you'll need to keep track of how time has already gone by. (I'd use my $wait_til = time() + timeout(); up front, and pass $wait_til - time() to can_read, after checking if it's positive or not.)
sockproperly initialized and does it refer to a socket in a valid state (open, no errors)? - rveerd