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

I am using Net::SSH2 module to make ssh connections to remote machines. I am trying to invoke these ssh connections as threads, and am getting the below errors :

Attempt to free non-existent shared string 'io_socket_type', Perl inte +rpreter: 0x84972e0 during global destruction. Attempt to free non-existent shared string 'io_socket_proto', Perl int +erpreter: 0x84972e0 during global destruction. Attempt to free non-existent shared string 'io_socket_domain', Perl in +terpreter: 0x84972e0 during global destruction. Attempt to free non-existent shared string 'io_socket_timeout', Perl i +nterpreter: 0x84972e0 during global destruction.
Here's the code sample that I am using :

Package code:

package sshConnector; sub new { my $class = shift; my $deviceInfo = shift; my $self = {}; my $ssh2; my ($ip,$port,$username,$password) = @$deviceInfo; # Invoke an ssh connection to the device eval { $ssh2 = Net::SSH2->new(); $ssh2->connect($ip,$port) or die }; if ($@) { print "Failed to make connection $@\n"; return 1; } # Send credentials for authentication my $res; if ($res = $ssh2->auth_keyboard($username, $password)) { $self->{'HANDLE'} = $ssh2; } return $self; } sub cmd { my $self = shift; my $cmd = shift; my $bufLength = 10000; my $connHandle = $sshHandle->channel(); # Make the connection blocking - wait until cmd exits $connHandle->blocking(1); # Merge the stderr contents also into the stdout buffer $connHandle->ext_data('merge'); # Execute the command eval { $connHandle->exec($cmd); }; if ($@) { print "Failed to execute cmd\n"; return 1; } # Initialize the buffer with all 0s $buf = '0' x $bufLength; # Read the buffer if anything is present in the output $connHandle->read($buf,$bufLength)) { $output = $buf; $exitStatus = $connHandle->exit_status(); print "output is $output, exit status is $exitStatus\n"; $connHandle->exec('exit'); $connHandle->close; return ($exitStatus,$output); } 1;

Script:

use sshConnector; my $machine1 = new Connector($deviceInfo1); my $machine2 = new Connector($deviceInfo2); sub methodA { my $self = shift; my $count = shift; my $hostname; while ($count) { ($status,$hostname) = $self->cmd("hostname"); print "$count : $hostname\n"; sleep 1; $count--; } } sub methodB { my $self = shift; my $count = shift; my $hostname; while ($count) { ($status,$hostname) = $self->cmd("hostname"); print "$count : $hostname\n"; sleep 2; $count--; } } my $thr1 = threads->create('methodA',$machine1,10); my $thr2 = threads->create('methodB',$machine2,6); $thr1->join(); print "First thread over\n"; $thr2->join(); print "Second thread over\n";

The threads started and continued till end, but the script exits before printing the last two print statements. Can someone please help? Why am I getting this error? Net-SSH2 is a threadsafe module, as far as I know. Am I missing something?

Regards, Madhuri
  • Comment on Attempt to free non-existent shared string 'io_socket_type', Perl interpreter: 0x84972e0 during global destruction.
  • Select or Download Code

Replies are listed 'Best First'.
Re: Attempt to free non-existent shared string 'io_socket_type', Perl interpreter: 0x84972e0 during global destruction.
by ikegami (Patriarch) on Dec 14, 2009 at 07:50 UTC

    I recognize those as being from IO::Socket. Presumably, IO::Sockets objects can't be shared. Create your connection in the thread where you use it. Your current model doesn't make much sense anyway. Why would you do the slow operation of connecting outside of the thread only to pass the object to the thread?

    sub method { my ($self, $deviceInfo, $count) = @_; my $machine = Connector->new($deviceInfo); while ($count) { my ($status, $hostname) = $self->cmd("hostname"); print "$count: $hostname\n"; sleep 1; --$count; } } my $thr1 = threads->create( 'method', $deviceInfo1, 10 ); my $thr2 = threads->create( 'method', $deviceInfo2, 6 );

    Net-SSH2 is a threadsafe module, as far as I know.

    What gives you that idea? That's a dangerous assumption to make, especially where XS code and external libraries are concerned.

      Thanks for this solution ikegami. But, I need to call different methods doing different long operations simultaneously. For example, keep writing data in one method, and keep checking the CPU load from the other method. Both these methods should be called on the same remote machine, ie. on the same object. Can there be a solution for having the object creation outside the thread?

        The problem arises because the destructor for the shared object is being called from each thread that has a copy of it.

        One way to avoid that is to add your own destructor method and defer destruction until the called by the last thread that has a copy.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Attempt to free non-existent shared string 'io_socket_type', Perl interpreter: 0x84972e0 during global destruction.
by BrowserUk (Patriarch) on Dec 14, 2009 at 07:28 UTC

    Try adding \n to each of the print statements.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      The problem is not just about the print statement. The problem is about the error 'attempt to free non-existent shared string' sent by the Perl interpreter.