Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Re: using SSH2 backend

by zentara (Archbishop)
on Sep 28, 2018 at 12:06 UTC ( #1223221=note: print w/replies, xml ) Need Help??

in reply to using SSH2 backend

Have you seen Net::SSH2 just hangs up without any output. Why not try commenting out any lines relating to blocking?


I was trying to figure out the confusing blocking problem, and came across this in the perldoc

blocking ( flag ) Enable or disable blocking. A good number of the methods in Net::SSH2/libssh2 can not work in non- +blocking mode. Some of them may just forcibly enable blocking during +its execution. A few may even corrupt the SSH session or crash the pr +ogram. The ones that can be safely called are read and, with some caveats, wr +ite. See "write" in Net::SSH2::Channel. Don't hesitate to report any bug you found in that area!
It would seem that with the shell() method, you may need blocking(0). I suggest trying both ways. :-)

Maybe the resident expert Salva would explain exactly what blocking() does, so we can sort this out once and for all.

Here is a plausible explanation: blocking vs non-blocking Which says:

The reason is that if you want to do two things at once, say read from + some other network connection, and your SSH session, you have two options: use blocking APIs, and use two threads or processes so you can do +them both use non-blocking APIs so the same thread can do both This latter approach is called Asynchronous I/O. See for example twist +ed which uses it extensively.

I'm not really a human, but I play one on earth. ..... an animated JAPH

Replies are listed 'Best First'.
Re^2: using SSH2 backend
by salva (Abbot) on Oct 01, 2018 at 09:17 UTC
    Maybe the resident expert Salva would explain exactly what blocking() does, so we can sort this out once and for all.
    blocking is just a wrapper for the libssh2 method libssh2_session_set_blocking.

    When blocking is active (the default), any method called will wait for the requested action to be completed before returning control to the caller.

    When it is deactivated, method calls that can not be fulfilled immediately return the libssh2 equivalent of an EAGAIN error, LIBSSH2_ERROR_EAGAIN.

    Unfortunately, the internal design of libssh2 for non-blocking mode is not very good and it imposes several limitations on how it can be used (for instance, once you get a LIBSSH2_ERROR_EAGAIN error, you are only allowed to retry just the failed method call with exactly the same arguments -at the C level- until it returns success). It is also quite buggy, so things that should work doesn't, not all the methods in the library are supported, and some even may corrupt the session.

    My experience when using it for more than trivial things, is that you often need to look into the C library and the XS code in order to see what is going on, and to work around all its quirks.

      Thanks, salva, your explanation seemed to play out on my command line:

      The way forward in mind was to make lexical variables of the blocking, so that the entire perl syntax could be brought to bear:

      my $ssh2 = get_tiny_ssh2(); my $block1 = 0; my $block2 = 0; my $block3 = 0; my $chan = $ssh2->channel(); $chan->blocking($block1); $chan->exec('ls -la'); while (<$chan>) { print } $chan->close; #shell use my $chan2 = $ssh2->channel(); $chan2->blocking($block2); #line 21


      Calling Net::SSH2::Channel::readline in non-blocking mode is usually a + programming error at ./ line 16. Can't call method "blocking" on an undefined value at ./ li +ne 21. $

      It seems to be the next blocking call in analogous fashion that draws an error. As this is described by a flag, ergo one or zero as the logical values we all know, it shouldn't take a whole lot of effort to enumerate the possibilities.

      It helps me to get a feel for the software to run it with different values. There's a little something learned with each failure:

      Can't call method "error" on an undefined value at /usr/local/share/pe +rl/5.26.1/Net/SFTP/Foreign/Backend/ line 43. $ cat ... my $block1 = 1; my $block2 = 1; my $block3 = 0; my $chan = $ssh2->channel(); $chan->blocking($block1); $chan->exec('ls -la'); while (<$chan>) { print } $chan->close; #shell use my $chan2 = $ssh2->channel(); $chan2->blocking($block2); $chan2->shell(); print $chan2 "uname -a\n"; print "LINE : $_" while <$chan2>; $chan2->close; say "execution goes through here"; my $chan3 = $ssh2->channel(); $chan3->blocking($block3); ##line 43 $chan3->exec('pwd'); while (<$chan>) { print } $chan3->close;

      But after a while you realize, gosh, I'm getting blocked no matter what I do with calls to 3 different channels. Some things happen; some don't:

      drwxr-xr-x 2 u61210220 ftpusers 61 Jun 9 2011 zen libssh2_channel_open_ex(ss->session, mandatory_type, strlen(mandatory_ +type), window_size, packet_size, ((void *)0) , 0 ) -> 0x0 Can't call method "blocking" on an undefined value at ./ li +ne 23. Net::SSH2::Channel::DESTROY Net::SSH2::DESTROY object 0xbd630ac0 $

      With debug set to one, I'm reading something here, but

      Net::SSH2::Channel::read(size = 4, ext = 0) - read 4 bytes - read 4 total Net::SSH2::Channel::read(size = 150, ext = 0) - read 150 bytes - read 150 total Net::SSH2::Channel::read(size = 4, ext = 0) - read 4 bytes - read 4 total Net::SSH2::Channel::read(size = 29, ext = 0) - read 29 bytes - read 29 total Can't call method "read" on an undefined value at ./ line 4 +2. Net::SSH2::Channel::DESTROY Net::SSH2::Channel::DESTROY Net::SSH2::Channel::DESTROY Net::SSH2::Channel::DESTROY Net::SSH2::DESTROY object 0xc71e2800

      What I find revealing here is that all the channels are destroyed at the very end. Those close calls aren't doing a thing. I tried changing up the blocking scheme:

      my $block1 = 1; my $block2 = 1; my $block3 = 1; my $chan = $ssh2->channel(); $chan->blocking($block1); $chan->exec('ls -la'); while (<$chan>) { print } $block1 = 0; $chan->blocking($block1); $chan->close;

      This draws an error:

      Can't call method "blocking" on an undefined value at ./ line 23.

      It seems there are several threads that go like mine here, where there is little resolution for the difficulties attending to using this particular SSH2 implementation as of this writing. I am well aware that many of the peripheral software changes in perl happen at the hands of people who are much better at it than me, and like me, volunteer their time to promote open source solutions. It's one thing I like about perl so much. (I'm so glad that I left FORTRAN for C, and c for perl.) There's nothing stopping anyone from calling all those libraries we knew. P.J. Plauger was kind enough to share his source with me for _The Standard C Library_, where the math library was good enough for the time. But what with the newer ones just off the griddle? The math gets a lot harder in contemporary encryption scenarios.

      I have more imaginative failures to post and found errors in my script, but I just felt successfully blocked, even when I tried to lower the number of channels to one. Either there is some hobgoblin sitting on my router that prevents ssh2 whilst allowing facebook, or I think I can say that I was unable to use this library.

      I see downthread that you suggested an alternative, which I will try. Thx for the informative write-up.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1223221]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2020-02-26 10:53 GMT
Find Nodes?
    Voting Booth?
    What numbers are you going to focus on primarily in 2020?

    Results (113 votes). Check out past polls.