in reply to Net::FTP Wrapper: TCP problem

One place you can have a problem with Net::FTP is if you somehow have an intermediate copy of the '$ftp' object returned by ``new Net::FTP''.

When Net::FTP times out or looses a connection, it undefs the object that the method which discovers the broken connection is called on -- that is, the object which is an object method's first arg.

Your ``$_[0]->get('connection')'' is the right idea; you don't ``my $ftp = shift;'' first, which would leave your caller's obj ($_[0]) still defined. But I can't see if you're doing that for the entire path.

(I'm sure this is clear as mud, but if you're in this package up to your elbows anyway, maybe you can follow what I'm talking about.)

  p

Replies are listed 'Best First'.
Re: Re: Net::FTP Wrapper: TCP problem
by graq (Curate) on May 31, 2001 at 17:14 UTC
    Whenever I am finished with the $ftp object, I call 'close' on it.
    There is no evidence of preceding connections failing at all before the connection that hangs.

    This is the base object (re: $_[0]->get('connection'):

    sub get { my ($self, $property) = @_; if ($#_ == 0) { return map {$_, $self->{'properties'}->{$_}} $self->properties +; } # if $property is an array, return all values if ( ref $property eq 'ARRAY') { my %retHash = (); grep {$retHash{$_} = $self->{'properties'}->{$_}} @$property; return \%retHash; } return $self->{'properties'}->{$property}; }
    Are you saying that this will cause the $ftp instance to be recreated?

    If so, why does this cause sporadic failure rather than constant failure or regular failure?
    --
    Graq

      Not 'recreated', but what _can_ happen is that you call an ftp command: ``$ftp->cmd(@args);''   which, as you know, is translated by perl as: Package::cmd($ftp, cmd, @args) ((here package is Net::FTP::...)).

      Inside cmd($ftp, ...), it does an ``undef $_[0];'' if, and only if, it discovers a broken connection.

      Next time you want to do an ftp cmd, you retrieve your _stored_ $ftp, (which is still defined and therefore still pointing to the right package::funcs) and send off another command.   ...Result, it hangs...

      For instance, here's the ``put()'', I've used for a couple of years in my wrapper code:
      # put: return ok = '' if 'no permission' error (ie, don't retry) sub put { $_[0]->SUPER::put(@_[1..$#_]) # rtns ok/!ok;$_[0] undef'd if abort or check($_[0]) # $_[0] can be undef'd here to hangup }
      (and in ``check()'':)
      . . . if ($code == 000 || # got here w/ no resp $code == '021' || $code == 421 || # server timeout || abort $code == 425 || # connection not opened ('out of ports'?) $code == 150) { # intermediate result (never finished) $code < 100 and warn " No response (Timeout?).\n"; 150 == $code and warn "\tTimed out in mid-operation.\n"; 421 == $code and warn "\tServer disconnected.\n"; 425 == $code and warn "\tRestarting to clear connections.\n" and sleep 10; warn "attempting to reconnect? ...\n"; undef $_[0]; return undef; } if ($code == 530) { # not logged in! ** needs to croak() ** die "Can't seem to login! (check ~/.netrc file or give name and password on command line?). (I'm dieing) \n"; } if ( $code == 550 # dir/file not available (non-exist, no perms) || (500 <= $code && $code <= 504) # syntax errors || $code == 553 # illegal file name || $code == 452 || $code == 552 ) { # out of space(552: quota) return ''; } if ($code == 426 # closed early || $code == 450 || $code == 451 # file busy, srvr local error || $code == '051') { # added this: local rcv error warn "\tTemporary failure, retrying...\n"; sleep 12; return undef; # retry }


        p