Subject: | syswrite fails with EAGAIN on AIX |
On AIX 5.2 and 5.3 in Net-SFTP-Foreign-1.62 and 1.55 we are seeing
syswrite occasionally fail with EAGAIN due to "Resource temporarily
unavailable", which is not a fatal error. The code in
Net::SFTP::Foreign treats all failures of syswrite as fatal. When a
file descriptor is using O_NONBLOCK, a syswrite that returns EAGAIN is
not fatal and can be retried.
To correct the problem I changed these lines in Unix.pm in version
1.62, or in Foreign.pm in version 1.55:
unless ($written) {
$sftp->_conn_lost;
return undef;
}
substr($$bout, 0, $written, '');
to this:
unless ($written) {
if ($! != EAGAIN ) {
$sftp->_conn_lost;
return undef;
}
}
substr($$bout, 0, $written, '') if ($written);
and added this near the beginning:
use Errno qw(EAGAIN);
Later I changed the above logic so it logs the "Resource temporarily
unavailable" condition when debug is set.
if ( ! $written) {
if ($! == EAGAIN ) {
$debug and $debug & 32 and _debug("syswrite: $!");
} else {
$sftp->_conn_lost;
return undef;
}
} else {
substr($$bout, 0, $written, '');
}
Sample debug messages (excerpt):
# waiting for message... [7]
# _do_io connected: 1
# _do_io select(-,-,-, undef)
# _do_io write queue: 67432, syswrite: 16384, max: 65536, $!:
# _do_io select(-,-,-, undef)
# _do_io write queue: 51048, syswrite: 16384, max: 65536, $!:
# _do_io select(-,-,-, undef)
# _do_io write queue: 34664, syswrite: 16384, max: 65536, $!:
# _do_io select(-,-,-, undef)
# _do_io write queue: 18280, syswrite: undef, max: 65536, $!: Resource
temporarily unavailable
# syswrite: Resource temporarily unavailable
# _do_io select(-,-,-, undef)
# _do_io write queue: 18280, syswrite: 18280, max: 65536, $!:
# _do_io read sysread: 28, total read: 28, $!:
# got it!, len:24, code:101, id:503, status: 0
65 00 00 01 f7 00 00 00 00 00 00 00 07 53 75 63 63 65 73 73 00 00 00
00 | e............Success....
# waiting for message... [6]
Diff for the simple changes:
diff -C 3 Unix.orig Unix.pm
*** Unix.orig Mon Aug 2 09:56:01 2010
--- Unix.pm Mon Nov 8 19:57:16 2010
***************
*** 14,19 ****
--- 14,20 ----
use Net::SFTP::Foreign::Helpers qw(_tcroak _ensure_list _debug
_hexdump $debug);
use Net::SFTP::Foreign::Constants qw(SSH2_FX_BAD_MESSAGE
SFTP_ERR_REMOTE_BAD_MESSAGE);
+ use Errno qw(EAGAIN);
sub _new { shift }
***************
*** 296,305 ****
$debug & 2048 and $written and _hexdump(substr
($$bout, 0, $written));
}
unless ($written) {
! $sftp->_conn_lost;
! return undef;
}
! substr($$bout, 0, $written, '');
}
if (vec($rv1, $fnoin, 1)) {
my $read = sysread($sftp->{ssh_in}, $$bin, 64 * 1024,
length($$bin));
--- 297,308 ----
$debug & 2048 and $written and _hexdump(substr
($$bout, 0, $written));
}
unless ($written) {
! if ($! != EAGAIN ) {
! $sftp->_conn_lost;
! return undef;
! }
}
! substr($$bout, 0, $written, '') if $written;
}
if (vec($rv1, $fnoin, 1)) {
my $read = sysread($sftp->{ssh_in}, $$bin, 64 * 1024,
length($$bin));
diff for the logging changes:
diff -C 3 Unix.orig Unix.pm
*** Unix.orig Mon Aug 2 09:56:01 2010
--- Unix.pm Mon Nov 8 20:22:46 2010
***************
*** 14,19 ****
--- 14,20 ----
use Net::SFTP::Foreign::Helpers qw(_tcroak _ensure_list _debug
_hexdump $debug);
use Net::SFTP::Foreign::Constants qw(SSH2_FX_BAD_MESSAGE
SFTP_ERR_REMOTE_BAD_MESSAGE);
+ use Errno qw(EAGAIN);
sub _new { shift }
***************
*** 295,305 ****
64 * 1024, $!);
$debug & 2048 and $written and _hexdump(substr
($$bout, 0, $written));
}
! unless ($written) {
! $sftp->_conn_lost;
! return undef;
}
- substr($$bout, 0, $written, '');
}
if (vec($rv1, $fnoin, 1)) {
my $read = sysread($sftp->{ssh_in}, $$bin, 64 * 1024,
length($$bin));
--- 296,311 ----
64 * 1024, $!);
$debug & 2048 and $written and _hexdump(substr
($$bout, 0, $written));
}
! if ( ! $written) {
! if ($! == EAGAIN ) {
! $debug and $debug & 32 and _debug("syswrite:
$!");
! } else {
! $sftp->_conn_lost;
! return undef;
! }
! } else {
! substr($$bout, 0, $written, '');
}
}
if (vec($rv1, $fnoin, 1)) {
my $read = sysread($sftp->{ssh_in}, $$bin, 64 * 1024,
length($$bin));
perl -v
This is perl, v5.8.8 built for aix-thread-multi
uname -a
AIX hostname 3 5
Regards,
Bill Godfrey