Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Net-SSH2 CPAN distribution.

Report information
The Basics
Id:
31083
Status:
resolved
Priority:
Low/Low
Queue:

People
Owner:
Nobody in particular
Requestors:
george.king [...] tropos.com
Cc:
AdminCc:



Subject: channel->read problems with exec and shell
I have encountered two problems with reading output from channels. The first is that shell channels return undef from reads. the diamond operator successfully reads from shell channels, but ext_data('merge') does not appear to work in this case. The second is that exec channels hang when reading via the diamond operator, but work fine with explicit read commands. ext_data('merge') works here. Attached are files that demonstrate the problem. SSH2Runs.pl should successfully execute and demonstrate the ext_data('merge') issue. SSH2Hangs.pl demonstrates the read undef problem, followed by the read hang. I am not sure if this is a Net::SSH2 problem or a libssh2 problem, but I thought I'd start here. I've also noticed that the placement of a $channel->blocking(0) call immediately after the creation of a channel is critical if the channel is to be used for a shell. Perhaps this hint could be added, to the documentation. These issues are occurring on Fedora 8 / x86. Please let me know if I can provide any assistance. I'm not familiar with xs bindings but I have a serious interest in making this module robust.
Subject: SSH2Hangs.pl
#!/usr/bin/perl use strict; use warnings; require 'SSH2Wrapper.pl'; my $ssh; my $channel; Net::SSH2->debug(1); if (1) { print "***** Test Single Shell With Read *****\n"; $ssh = wrapConnect(); $channel = $ssh->channel() or die 'could not create channel'; $channel->blocking(0); # the placement of this call is critical $channel->shell(); print $channel "pwd\n"; print "** BROKEN: channel->read returns undef!: **\n"; printOutputSeperate($channel); print $channel "ls zzzzzzzzz\n"; print "** BROKEN: channel->read returns undef!: **\n"; printOutputSeperate($channel); undef $ssh; undef $channel; } if (1) { print "***** Test Multiple Channel Execs With Diamond *****\n"; $ssh = wrapConnect(); $channel = $ssh->channel() or die 'could not create channel'; # $channel->ext_data('normal'); # default $channel->exec('pwd'); print "** BROKEN: channel->read hangs on poll!: **\n"; printOutputDiamond($channel); print "I NEVER GET HERE!!\n"; # $channel = $ssh->channel() or die 'could not create channel'; # $channel->ext_data('merge'); $channel->exec('ls zzzzzzzzz'); print "** BROKEN: channel->read hangs on poll!: **\n"; printOutputDiamond($channel); print "I REALLY NEVER GET HERE!!\n"; }
Subject: SSH2Wrapper.pl
#!/usr/bin/perl use strict; use warnings; use Net::SSH2; my @poll_events = qw( in pri ext out ); my @poll_revents = qw( err hup session_closed nval ex channel_closed listener_closed ); sub wrapConnect { my $ssh = Net::SSH2->new(); $ssh->connect('10.245.2.11') or die 'connect failed'; $ssh->auth_publickey('root', '/home/george/.ssh/id_rsa.pub', '/home/george/.ssh/id_rsa') or die 'Authentication failed'; return $ssh; } sub printOutputSeperate($) { my ($channel) = @_; my $buffer; my $string = ''; while ($channel->read($buffer, 512) > 0) { $string .= $buffer; } print "STDOUT: $string\n"; $string = ''; while ($channel->read($buffer, 512, 1) > 0) { $string .= $buffer; } print "STDERR: $string\n"; print "EXIT: " . $channel->exit_status() . "\n"; } sub printOutputDiamond($) { my ($channel) = @_; my $string = ''; $string .= $_ while (<$channel>); print "HANDLE OUT: $string\n"; print "EXIT: " . $channel->exit_status() . "\n"; } 1;
Subject: SSH2Runs.pl
#!/usr/bin/perl use strict; use warnings; require 'SSH2Wrapper.pl'; my $ssh; my $channel; Net::SSH2->debug(1); if (1) { print "***** Test Single Shell With Diamond *****\n"; $ssh = wrapConnect(); $channel = $ssh->channel() or die 'could not create channel'; $channel->blocking(0); # the placement of this call is critical $channel->ext_data('merge'); # merge is broken for shell $channel->shell(); print $channel "pwd\n"; print "** stdout works: **\n"; printOutputDiamond($channel); print $channel "ls zzzzzzzzz\n"; print "** BROKEN: merged output should show stderr and exit status 1: **\n"; printOutputDiamond($channel); undef $ssh; undef $channel; } if (1) { print "***** Test Multiple Channel Execs With Read *****\n"; $ssh = wrapConnect(); $channel = $ssh->channel() or die 'could not create channel'; # $channel->ext_data('normal'); # default $channel->exec('pwd'); print "** stdout works: **\n"; printOutputSeperate($channel); $channel = $ssh->channel() or die 'could not create channel'; # $channel->ext_data('merge'); # merge does work here $channel->exec('ls zzzzzzzzz'); print "** seperate stderr works: **\n"; printOutputSeperate($channel); }
These bugs have already been fixed in the development version. Only one exec/shell/tcpip/etc. call is possible per Channel. There is no way in the libssh2 API to detect when some channel has already been used in order to throw an error.


This service runs on Request Tracker, is sponsored by The Perl Foundation, and maintained by Best Practical Solutions.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.