in reply to Re: Net:FTP timeout handaling
in thread Net:FTP timeout handaling
Looked at this all night and my conclusion is that FTP is bulloxed, at least on my server. I first verified your code. I took Zippy, a Sharp SL-5500 PDA running Linux, and plugged it into a usb port. Zippy has a pftp server running on port 4242. I ran your code as is and verified that it successfully pulled a directory list. Success.
I then opened four telnet sessions into the PDA and ran four copies of a simple screen scroller to keep the IO busy. Reducing the ftp timeout value to one second; I was able to generate multiple timeouts while trying to fetch a simple directory structure.
From there things went from bad to worse. The problem, I concluded is that, once there is an I/O error, the client and the server become out of sync. On receiving and error Net::FTP exits returning an undef, and your script goes on it's merry way, but the server is still busy trying to process the original GET request. If I issue a new GET request to the same directory I get and error for the new socket and I see the old socket trying to complete it's request. I tried to to figure out a way to reset the server but my server doesn't handle RETR requests and ABOR didn't seem to behave as the manual indicated.
Here is what I was trying to do:
Note that I assign the results of ftp->dir() to a scalar. Assigning it to a hash is trouble. As in the original code, the assignment $hash{}=$ftp->dir() behaves poorly when faced with and I/O error. On error ftp->dir() returns an undef. When assigned to a hash this deletes the hash key. Any subsequent attempt to test against that key fails as the key is does not exists in the symbol table. You get an error reading "must supply package name for $hash" Much better to assign to a $arrayref. Then you can do a conditional on the $arrayref like do{}while($arrayref); or print if $arrayref;foreach my $remote_in_dir (@remote_in_dir_list) { my $arrayref; # ftp returning an undef in scalar context is so not usefu +l. do { $arrayref = $ftp->dir("$remote_dir/$remote_in_dir"); # This kills more than the current operation # Could be a local problem, need to try a different se +rver. $ftp->_ABOR unless $arrayref; } until $arrayref; $file_list{$remote_dir}{$remote_in_dir} = $arrayref; . . . }
I'm really quite flummoxed at this point. I need to repeat this with a different ftp server but I have already spent to much time on it and building another server isn't what I wanted to do today. I hope some other monk here can add more in way of illuminating this discussion.
No, I don't think alarms are a solution as I think you will still have the problem of the server being out of sync with the client. Better to fix the code as above to correctly detect the ftp->dir(), failure and then figure out a way to reset the session at the server.
|
|---|