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

I have written code to create threads with the information need to start an SNMP session in each thread.
my $thr = threads->create(\&test,"host","string","2");
when I involve more than one thread I only get information back from one thread as if all other sessions were stopped. Here is part of the code involved in addition to the snippet above.
sub test{ my ($SNMP_TARGET, $SNMP_COMMUNITY,$SNMP_VERSION) = @_; my $SESSION = new SNMP::Session (DestHost =>$SNMP_TARGET, Community =>$SNMP_COMMUNITY, Version => $SNMP_VERSION ); my $VLIST = new SNMP::VarList(['sysDescr',0], #0 ['sysObjectID',0], #1 ['sysUpTime',0], #2 ['sysContact',0], #3 ['sysName',0], #4 ['sysLocation',0], #5 ['sysServices',0]); #6 my @a = $SESSION->get($VLIST); print "$a[0]\n"; }
Using fork() has been recommended to me before, I really want to use threads, so any help in getting the required solution will be great! Thank you in advance

Replies are listed 'Best First'.
Re: threads and SNMP Session
by renodino (Curate) on Dec 19, 2005 at 22:56 UTC
    The following info may help diagnose things:

    1. Perl version (all 3 digits)
    2. O/S and platform information

    Also, have you tested that everything works when you *don't* use threads, i.e., the first host gets dumped out, then the 2nd ?

      Perl version is 5.8.5 Platform: Gentoo linux Yes, it does work if i dont use threads. It also works if I add  sleep 1; to the subroutine test before printing the info. Hope this helps!
        I didn't see a join() anywhere in your app (which may explain your ability to get a result w/ sleep 1). After you spawn your threads, you need to explicitly wait for them all to complete via:
        $thr->join(); $thr2->join(); ...etc...
        Otherwise the main thread will just exit, which may cause the child threads to get prematurely killed.
Re: threads and SNMP Session
by zentara (Cardinal) on Dec 19, 2005 at 22:08 UTC
    Hi, I've no experience with SNMP and threads, but you really need to show us a bit more code. You only show 1 thread being created, but you talk about multiple threads. Are you sure you are not overwriting threads, so it seems like you are stopping the others?

    I'm not really a human, but I play one on earth. flash japh
      when testing I just add
      my thr = threads->create(\&test,"host","string","2"); my thr2 = threads->create(\&test,"newhost","string","2");
      to the code and no matter how many threads I add the last one is the only one to return data. I dont know what else to add if you require anything more please tell me. thanks.
      when testing I just add
      my thr = threads->create(\&test,"host","string","2"); my thr2 = threads->create(\&test,"newhost","string","2");
      to the code and no matter how many threads I add the last one is the only one to return data. I dont know what else to add if you require anything more please tell me. thanks.
Re: threads and SNMP Session
by BrowserUk (Patriarch) on Dec 19, 2005 at 23:55 UTC

    I think you may be out of luck with using this module and threads together, From a cursory browse of the XS component of this module, it seems to make extensive use of static data areas. If my reading is correct, the module will be trying to reuse those same static C variables in conjunction with all your threads, and that obviously isn't going to work.

    However, from a cursory reading of the docs, you probably don't need to be using threading or forks for this. The module has built in asynchronous capabilities. You simply pass a callback address on each (f)get(next)() of set() call and then enter it's event loop &SNMP::MainLoop([<timeout>, [<callback>]]) and your queries will call your code when the results arrive.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      While searching on the internet I found many references to this solution yet no example that implements it or good documentation. If you know of any please post the links. Thank you

        If you are issuing identical requests to multiple hosts, you can just use SNMP::Multi and forget about the details :)

        If not, take a look at the source for SNMP::Multi, in particular the request() & execute() subs, to see what needs to be done. Basically, loop over the hosts issuing your get()s and passing a callback, (closures would be good here), and then enter the MainLoop and allow it to go to work.

        Of course, there's a bit more to it that that with timeouts, retries and collating the information returned.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: threads and SNMP Session
by leighsharpe (Monk) on Dec 20, 2005 at 03:11 UTC
    What exactly are you trying to acheive? If you are polling multiple hosts, starting a new thread for each device could cause you some scalability problems. I had a similar situation a few years ago. Over about 50 hosts, and the overhead required for each new process killed the PC. Using Net::SNMP in non-blocking mode allows you to do the job. In my case, I'm now polling about 200 devices at once, and all polls are fiinshed in about 12 seconds. Is this what you're trying to do, or am I way off?
      I'm doing a walk on a each device for example to get the interface information on over 1000 devices at the same time ( it depends on whats needed by the engineer). I decided to leave the threads implementation because of the huge overhead and im currently using fork to initiate about 10 process to start each session with each device and its still not fast enough. I would appreciate if you go into more detail about your implementation. Thanks!
        You will need to read the Net::SNMP documentation several times before it sinks in properly, I found. Here's a quick example of how to get the IfInOctets and IfOutOctets for interface number 1 on multiple hosts in one hit. It's not much different from the examples in the docs, though:
        use warnings; use strict; use Net::SNMP; my $community="public"; # community string for devices my $interface_number=1; # interface number to poll my @ip_addresses=("192.168.5.242","192.168.11.34"); # Queue up a request to each host. foreach (@ip_addresses) { my ($session,$error)=Net::SNMP->session(-hostname=>"$_", -nonblocking=>1, -community=>"$community", -timeout=>2, -retries=>3, ); if (defined($session)) { my $in_oid=".1.3.6.1.2.1.2.2.1.10."."$interface_number"; # +OIDs to poll. my $out_oid=".1.3.6.1.2.1.2.2.1.16."."$interface_number"; my $uptime_oid=".1.3.6.1.2.1.1.3.0"; my @oids=($in_oid,$out_oid,$uptime_oid); my $result=$session->get_request( -varbindlist=>\@oids, callback=>[\&reply,$interface_number,$_] ); } else { print "Session not defined! $error\n"; } } # All requests are queued. Now dispatch them. snmp_dispatcher(); exit; # Sub "reply" is executed for each response from remote hosts. sub reply { my $obj=shift; my $interface=shift; my $ip_address=shift; if (!defined($obj->var_bind_list)) { warn "$ip_address SNMP Error.",$obj->error(),"\n"; return; } my $in_oid=".1.3.6.1.2.1.2.2.1.10."."$interface"; my $out_oid =".1.3.6.1.2.1.2.2.1.16."."$interface"; my $uptime_oid=".1.3.6.1.2.1.1.3.0"; my $uptime=$obj->var_bind_list->{$uptime_oid}; my $in=$obj->var_bind_list->{$in_oid}; my $out=$obj->var_bind_list->{$out_oid}; print "$ip_address interface number $interface bytes in: $in bytes + out: $out Uptime $uptime\n"; }

        Keep these things in mind when designing this:
        In non-blocking mode, it will queue all requests without actually dispatching them until you execute the snmp_dispatcher.
        At that point, your program will block until all requests have been finished.
        Each time a response is recieved, it will call the 'reply' subroutine.
        You only get control back to the main program after all requests have either completed or timed out.
        Good luck.