Skip Menu |

This queue is for tickets about the Net-SFTP-Foreign CPAN distribution.

Report information
The Basics
Id: 62873
Status: resolved
Worked: 30 min
Priority: 0/
Queue: Net-SFTP-Foreign

People
Owner: salva [...] cpan.org
Requestors: yak36790 [...] yahoo.com
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in:
  • 1.55
  • 1.62
Fixed in: (no value)



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
Solved in 1.63_03 on CPAN now. Thank you for the bug report!
Subject: Re: [rt.cpan.org #62873] Resolved: syswrite fails with EAGAIN on AIX
Date: Fri, 19 Nov 2010 13:52:46 -0800 (PST)
To: bug-Net-SFTP-Foreign [...] rt.cpan.org
From: Bill Godfrey <yak36790 [...] yahoo.com>
Although the new versions 1.63_03 and 1.63_04 are working, I don't understand why the new versions check for EINTR. I understand EAGAIN because that is what my patch used, but I would think that EINTR would be a fatal error. Thanks for fixing the problem so quickly.   Bill Godfrey --- On Wed, 11/10/10, Salvador Fandino Garcia via RT <bug-Net-SFTP-Foreign@rt.cpan.org> wrote: From: Salvador Fandino Garcia via RT <bug-Net-SFTP-Foreign@rt.cpan.org> Subject: [rt.cpan.org #62873] Resolved: syswrite fails with EAGAIN on AIX To: yak36790@yahoo.com Date: Wednesday, November 10, 2010, 4:12 AM <URL: https://rt.cpan.org/Ticket/Display.html?id=62873 > According to our records, your request has been resolved. If you have any further questions or concerns, please respond to this message.
Subject: Re: [rt.cpan.org #62873] Resolved: syswrite fails with EAGAIN on AIX
Date: Sat, 20 Nov 2010 00:27:52 -0800 (PST)
To: bug-Net-SFTP-Foreign [...] rt.cpan.org
From: Salvador Fandino <sfandino [...] yahoo.com>
Show quoted text
----- Original Message ----
> From: Bill Godfrey via RT <bug-Net-SFTP-Foreign@rt.cpan.org> > Sent: Fri, November 19, 2010 11:19:35 PM > Subject: Re: [rt.cpan.org #62873] Resolved: syswrite fails with EAGAIN on AIX > > Queue: Net-SFTP-Foreign > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=62873 > > > Although the new versions 1.63_03 and 1.63_04 are working, I don't understand >why the new versions check for EINTR. I understand EAGAIN because that is what >my patch used, but I would think that EINTR would be a fatal error. Thanks for >fixing the problem so quickly.
EINTR will arrive because of signals happening during IO operations. If the signal is a fatal error, for instance, and unhandled INT, it will just make the program die jumping to some higher level in the calling stack. Cheers, - Salva