Dne Ne 02.dub.2006 16:12:04, guest napsal(a):
Show quoted text> Net::FTP seems to have a bug when ABORting a file transfer on a slow
> connection in version 1.19. When the connection is closed via
> Net::FTP::dataconn::close, line 65 in that module tries to read a single
> character with a zero timeout. For binary files, that call ends up in
> Net::FTP::I::read, which at line 24 says:
>
> $data->can_read($timeout) or
> croak "Timeout";
>
> Since the timeout is 0, this is essentially a nonblocking poll; if there
> doesn't happen to be any data available at the time this is called and
> we're not at EOF, it croaks.
>
> I'm not sure why it's trying to read a single byte there; to detect EOF,
> maybe? I tried removing the read at Net::FTP::dataconn.pm:65 and
> everything worked OK. Another possibility is to use a timeout of undef
> instead of 0, which would cause select to block indefinitely.
>
> I can reproduce this by connecting to a slow CPAN server, starting a
> file transfer with retr, then closing the dataconn before reaching EOF.
>
It seems to be resolved with this commit:
commit c37154d1b5c996d12c62dd4ac641f676dc0b3c70
Author: Graham Barr <gbarr@pobox.com>
Date: Sun Feb 10 01:56:05 2008 +0000
Catch timeout condition while doing an abort
diff --git a/Net/FTP/dataconn.pm b/Net/FTP/dataconn.pm
index e7645cb..bc6ba7f 100644
--- a/Net/FTP/dataconn.pm
+++ b/Net/FTP/dataconn.pm
@@ -63,7 +63,7 @@ sub close {
if (exists ${*$data}{'net_ftp_bytesread'} && !${*$data}{'net_ftp_eof'}) {
my $junk;
- $data->read($junk, 1, 0);
+ eval { local($SIG{__DIE__}); $data->read($junk, 1, 0) };
return $data->abort unless ${*$data}{'net_ftp_eof'};
}
I agree with the reporter that the read() actually does not handle 0 timeout properly and instead of masking the read() misuse there should be a better fix.
I can imagine the junk read is there to pick up a TCP close on the data stream and not to bother the server with an abort, but there is no guarantee that the TCP close will arrive and will be exposed as an EOF to the client in time (before "$data->abort unless ${*$data}{'net_ftp_eof'}" is executed).
In my opinion the close() call should be subject to the same timeout as read(). See abort() that actually does that (in some cases). And after the timeout if no EOF is available, an abort() should be executed.
If author does want to block in the close(), he should remove the junk read completely because it does bring any benefit.