in reply to Using Net::SSH2 with Net::Telnet::Cisco

The FILENO issue that you are encountering is because Net::Telnet is trying to get a fileno that it can hand to C code which doesn't understand Perl filehandles. But it is implemented in Perl so there is no such fileno, and therefore no FILENO method implemented, and therefore you have a problem. That's a non-starter.

The first option is to stop using threads. This is not as crazy as it sounds. Try replacing threads with forks, and see if it works. If it does, then your thread problems may go away. If they don't go away, then be careful to require the module from within the same "thread" as you instantiate the object and they definitely should go away.

Another option is to create a standalone process that uses Net::Appliance::Session and Net::SSH::Perl which can be driven from within a thread in your main application. Be warned that this type of network programming usually takes more work than you were planning on.

The third option I see is to try to debug the thread problems in the original modules. I have no idea how easy or hard that will be. If you're lucky it will be as simple as not using the modules, but instead require them in the thread that you instantiate the objects from.

  • Comment on Re: Using Net::SSH2 with Net::Telnet::Cisco

Replies are listed 'Best First'.
Re^2: Using Net::SSH2 with Net::Telnet::Cisco
by Anonymous Monk on Jan 14, 2011 at 03:56 UTC

    Thanks for the response, Tilly. I actually just rewrote this app to use threads instead of fork, which was used in the previous version. I was able to get much greater concurrency with threads than I did with fork() and decreased the run time substantially. So, I really don't want to have to rewrite it again to use fork().

    With both Net::Appliance::Session and Net::SSH::Perl, I have the "use" statement in the subroutine that is called by the thread. In each case, I wrote a very simple program. The first version does not create any threads and just calls the subroutine- that works without an issue. Then I modify it so that the subroutine is called as one or more threads. The threaded versions fail consistently.

    I will post the sample programs with more details tomorrow (when I am on my work machine), but basically the Net::Appliance::Session version fails when Net::Appliance::Session::Transport::SSH forks and runs ssh and then tries to create a new IO::Pty object attached to it (I have since read the IO:Pty is not thread safe). The Net::SSH::Perl version will just crash with a Memory Fault at some point in its execution (I have since read that Math::PARI is not thread safe).

    I thought about trying what you are suggesting, where a separate process is invoked from the threads, but if I do that I may as well just rewrite to use fork().

    Thanks again for your comments (and any more you might have).

      As you can see from the docs below, "use" statements are processed before regular code. So I doubt putting them in the subroutine will accomplish what you want.
      use Module VERSION LIST use Module VERSION use Module LIST use Module use VERSION Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package. It is exactly equivalent to BEGIN { require Module; import Module LIST; } except that Module must be a bareword.
      In 882270 tilly suggested:
      The third option I see is to try to debug the thread problems in the original modules. I have no idea how easy or hard that will be. If you're lucky it will be as simple as not using the modules, but instead require them in the thread that you instantiate the objects from.
      Have you tried ditching "use" and go with "require" like he suggested? Seems like the next course of action to take.

      Elda Taluta; Sarks Sark; Ark Arks

        Thanks for your response, Argel. Yes, that did occur to me and I tried changing the "use" statements to require, but it did not make a difference. Both Net::Appliance::Session and Net::SSH::Perl still fail in the same way.

        I am now looking at trying to use Net::Telnet::Cisco on top of Net::SSH2. What I would like to do is create an SSH connection and pass an open filehandle to Net::Telnet. However, Net::SSH2 creates only a PERL filehandle, and Net::Telnet wants a filehandle implemented at the C level (or so is my understanding).

        Any thoughts on how I might be able to swing that? I was thinking I might be able to open a file on the underlying Unix system to which I could somehow pipe the PERL handle I got back from Net::SSH2

        Thanks, Ryan