roperl has asked for the wisdom of the Perl Monks concerning the following question:

I've have the following sub in my program
sub sftp_file { my ($file,$destfile,$host,$port,$user,$privpath,$pubpath,$pass) = +@_; my $ssh2 = Net::SSH2->new(); $ssh2->connect( $host,$port ) or $logger->info("Connect failed: $! +\n"); if ( !$ssh2->error ) { $ssh2->auth( username => $user, publickey => $pubpath, private +key => $privpath, password => $pass, passphrase => undef ) or $logger +->info("Authent ication failed: $!\n"); } if ( $ssh2->auth_ok ) { my $sftp = Net::SFTP::Foreign->new( ssh2 => $ssh2, backend => +'Net_SSH2' ); $sftp->error and $logger->info("Unable to establish SFTP conne +ction: $sftp->error\n"); $sftp->put( "$file", "$destfile", best_effort => 1 ) or ( $log +ger->info("Put failed: $sftp->error\n") && return ); return 1; } else { return 0; } }
The sub works fine if I call it before I startup and threads. If I call it in a thread I get the following error:
Connect failed: Resource temporarily unavailable
When I turn on tracing of libssh2 and debug I see the following
[libssh2] 0.822042 Transport: session_startup for socket 5 [libssh2] 0.822225 Transport: Sending Banner: SSH-2.0-libssh2_1.8.0 [libssh2] 0.822280 Socket: Sent 23/23 bytes at fe7b1570+0 [libssh2] 0.822334 Socket: Recved 0 bytes banner [libssh2] 0.822366 Failure Event: -13 - Failed getting banner Net::SSH2::DESTROY object 0x3413458 [libssh2] 0.825767 Transport: Freeing session resource [libssh2] 0.825807 Transport: Extra packets left 0 [libssh2] 0.825839 Transport: unable to reset socket's blocking state
Is there work around ?

Replies are listed 'Best First'.
Re: Net::SSH2 issue in thread
by Corion (Patriarch) on Jul 31, 2018 at 15:56 UTC

    I would avoid mixing threads and C libraries (in this case, Net::SSH2). Most likely, the C library is not really thread-safe and will only ever work from within one thread.

    You don't show how you start up threads and how your threads use the object and the function sftp_file. Maybe only ever using sftp_file from one thread might work, but that's hard to say without seeing the code you're actually using.

      According to the libssh2.org site, it is thread safe: "Thread-safe: just don't share handles simultaneously"

      I'm not sure if I am sharing handles simultaneously

      At the top of my code I call
      use Net::SSH2;
      Then I create my threads
      my $work_q = Thread::Queue->new(); my $thr = threads->new( 'file_worker', $work_q );
      In my file_work sub I call the sftp_file if the file is found and supply the required arguments
      my $retval = sftp_file($file,$destfile,$host,$port,$user,$privpath,$pu +bpath,$pass);
Re: Net::SSH2 issue in thread
by salva (Canon) on Aug 01, 2018 at 06:59 UTC
    Net::SSH2 is not thread safe.

    You might be able to use if from one thread, as far as objects are not shared between threads (and sharing could be just letting a Net::SSH2 object be cloned by creating a new thread even if it is not used there at all, see issue 40).

    I (the de-facto current maintainer of Net::SSH2) have looked into that a couple of times, but fixing all the issues involved in order to make the module just usable in a threaded environment would be a mayor effort and the reality is that I lack the time to do it. So, unless somebody volunteers to do it (or offers to fund it!) I don't see it being fixed.

      Salva,
      Thanks. I was hoping maybe there was a work around. Maybe I'll have my threaded program call another program that actually does the sftp.