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

im making a script with net::snmp and wanted to output the results on a textbox so after reading a while i managed to create a gui with a textbox and a button to start collecting info of routers. the problem i ran into is that im usync async calls with snmp and the gui simply freezes, it must be, either by the snmp_dispatcher function or because of the timeout. So after a while reading i saw someone suggested the DoOneevent; and used with not much luck. Is there a way for this script to stop freezing?? oh btw, do you know of any widget that might format the output to the textbox like this functions does?? "format STDOUT =" heres the code.
#!/usr/bin/perl -w use warnings 'all'; use strict; use Net::SNMP qw(snmp_dispatcher oid_lex_sort); use Tk; use Tk::LabEntry; my $pstme = localtime(); my $startip; my $endip; my $community; my $maxwork; my $mw = MainWindow->new(-width=>'300',-height=>'600'); #$mw->geometry("350x100"); $mw->resizable( 0, 0 ); $startip = '1.1.1.1'; $endip = '1.1.1.255'; $community = 'public'; $maxwork = '20'; my $ipmwf = $mw ->Frame ( -borderwidth=>3,-relief=>'flat' ) -> pack(-s +ide=>'top',-expand=>0,-fill=>'x'); my $from = $ipmwf->LabEntry(-borderwidth=>2,-background=>'White',-reli +ef=>'sunken', -label => "IP range: ", -labelPack=>[-side=>'left',-anchor=>'n' ], -width => 15, -textvariable => \$startip, )->pack(-side=>'left',-anchor=>'nw',-expand=>0,-fil +l=>'x',-pady=>3); my $to = $ipmwf->LabEntry(-borderwidth=>2,-background=>'White',-relief +=>'sunken', -label => " to ", -labelPack=>[-side=>'left',-anchor=>'n' ], -width => 15, -textvariable => \$endip, )->pack(-side=>'left',-anchor=>'nw',-expand=>0,-fil +l=>'x',-pady=>3); my $othfm = $mw ->Frame ( -borderwidth=>3,-relief=>'flat' ) -> pack(-s +ide=>'top',-expand=>0,-fill=>'x'); my $commst = $othfm->LabEntry(-borderwidth=>2,-background=>'White',-re +lief=>'sunken', -label => "Community String: ", -labelPack=>[-side=>'left',-anchor=>'w' ], -width => 15, -textvariable => \$community, )->pack(-side=>'left',-anchor=>'nw',-expand=>0,-fil +l=>'x',-pady=>3); my $inpthr = $othfm->LabEntry(-borderwidth=>2,-background=>'White',-re +lief=>'sunken', -label => "Threads: ", -labelPack=>[-side=>'left',-anchor=>'w' ], -width => 4, -textvariable => \$maxwork, )->pack(-side=>'left',-anchor=>'nw',-expand=>0,-fil +l=>'x',-pady=>3); my $strtbtn = $ipmwf->Button ( -overrelief=>'raised',-relief=>'raised' +,-text=>'Start Scan', -compound=>'none',-state=>'normal',-command => +\&Strtscan ) ->pack(-side=>'left',-padx=>8); my $infm = $mw ->Frame ( -borderwidth=>3,-relief=>'flat' ) -> pack(-si +de=>'top',-expand=>0,-fill=>'x'); my $infor = $infm -> Scrolled ( 'Text', -relief=>'sunken', -scrollbars=>'se', -wrap=>'none', -state=>'normal' ) -> pack(-side=>'left'); MainLoop(); { sub Strtscan { my $state = $strtbtn->cget('-state'); $strtbtn-> configure('-state' => 'disabled'); $strtbtn-> update; my $startip = $from->get(); my $endip = $to->get(); my $community = $commst->get(); my @ip_start = split(/\./,$startip); my @ip_end = split(/\./,$endip); { my $conter=0; my($i,$j,$k,$l); for ($l="$ip_start[0]";$l<="$ip_end[0]";$l++){ for ($i="$ip_start[1]";$i<="$ip_end[1]";$i++){ for ($j="$ip_start[2]";$j<="$ip_end[2]";$j++){ for ($k="$ip_start[3]";$k<="$ip_end[3]";$k++){ my ($session,$error)=Net::SNMP->session(-hostname=>"$l.$i.$j.$ +k",-version=>'snmpv2c',-nonblocking=>1,-community=>"$community",-time +out=>2,-retries=>1); if (defined($session)) { my $result=$session->get_request( -varbindlist=>['1.3.6.1.3.83.1.1.4.0','1.3.6.1.2.1.2.2.1.6 +.2'], callback=>[\&getms,$session,"$l.$i.$j.$k"] ); }else{ print "Session not defined! $error\n"; }; }; DoOneEvent(); snmp_dispatcher(); }; }; }; }; $strtbtn-> configure('-state' => 'active'); $strtbtn-> update; }; }; { sub getms { my $obj = shift; my $session = shift; my $ip = shift; if (!defined($obj->var_bind_list)) { $infor->insert('end',"$ip SNMP Error $obj->error() \n"); DoOneEvent(); return; }; }; };

Replies are listed 'Best First'.
Re: perl/tk script freezes
by graff (Chancellor) on Feb 07, 2008 at 14:08 UTC
    As originally posted, your script has the "DoOneEvent" call outside of the inner-most "for" loop, running the range of numbers in the fourth part of the IP addresses. If you have been trying the script with the default values for the start and stop IP addresses (1.1.1.1 - 1.1.1.255), this means that you run 255 iterations of the inner-most loop (calling Net::SNMP->session each time, with a 2-sec time-out) before you get to the first "DoOneEvent" call.

    Have you allowed the script to run for at least 8 min. 30 sec, to let that inner loop finish? How about putting the DoOneEvent call inside that loop, rather than after it? Better yet, you might want to add a label widget with a "-textvariable =>\$status_string option, update that variable with the ip address being scanned, and call that widget's update method within the inner-most loop, so you can see what's happening inside that loop as it happens.

    A few other comments about your code:

    • Since your "start-ip" and "end-ip" entry widgets use variables with the "-textvariable" option, why not just reference those variables in the Strtscan sub, rather than getting the values from the widgets?
    • You are using quotes around variables when you don't need to (e.g. in the C-style for loop conditions).
    • Maybe I'm missing something, but it looks like nothing happens in the Tk window unless there's an error in the SNMP $session->get_request call. So during all the time that the scan is moving along with no errors, nothing is showing up to tell the user what's happening. If there is nothing to be shown to the user except when there's an error, why is this a Tk GUI? (Why not just a plain-text command-line tool?)
Re: perl/tk script freezes
by starX (Chaplain) on Feb 07, 2008 at 13:57 UTC
    Is there a way for this script to stop freezing??

    Maybe.

    the problem i ran into is that im usync async calls with snmp and the gui simply freezes, it must be, either by the snmp_dispatcher function or because of the timeout.

    Have you tried the debugger to figure out which function is freezing? Even more specifically on which line it's freezing?

Re: perl/tk script freezes
by zentara (Cardinal) on Feb 07, 2008 at 17:17 UTC
    I agree with pc88mixer. You need to run the snmp code in a separate thread, or thru some IPC module( a fork). The reason do_one_event won't work, is that the snmp stuff hogs the execution pointer and won't let Tk get any control. There are alot of examples here and on groups.google for "Tk threads" and "Tk::IPC".

    Actually it look very easy to convert to threads.... just make your StrtScan sub a thread, create it before any Tk code is called, and remove any Tk code from it. Set up some shared variables, and a Tk::timer to read them from the thread, for inter-thread communication.

    I'm not familiar with Net::SNMP, but there MAY be a mechanism to get your script to work, like setting a timeout and running do_one_loop at each timeout, or possible Net::SNMP has a hook to run external code, in which you can do_one_loop.


    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: perl/tk script freezes
by thundergnat (Deacon) on Feb 07, 2008 at 20:38 UTC

    Instead of DoOneEvent() inside the Strtscan sub, try using $mw->update.

    On a side note; perltidy. Get it. Use it. You'll thank me. Really.

Re: perl/tk script freezes
by Anonymous Monk on Feb 07, 2008 at 14:45 UTC
    thx for your answers, i forgot to mention, i did put DoOneEvent in the inner loop, in the callback, i even replaced the callback function in the Net::snmp Session with DoOneEvent() and still got the same freeze
Re: perl/tk script freezes
by Anonymous Monk on Feb 07, 2008 at 14:49 UTC
    oh and yes, ive allowed for it to finish, when it does, it gives me results, the problem is that it freezes when waiting for the responses. so those ips are just for testing the problem so they give me timeout.
Re: perl/tk script freezes
by Anonymous Monk on Feb 07, 2008 at 14:55 UTC
    srry, didnt read your last comment, it does a lot more than that, but i started to split the script to find what might be the problem, until it came to this, so i think it must be the snmp_dispatcher which seem to be a loop that interferes with the Mainloop
      Could it be that snmp_dispatcher() doesn't return until "all queued SNMP messages have received a response or have timed out at the Transport Layer"? So it seems that during that time Tk will never have a chance to run.

      I would consider re-architecting this so that the SNMP stuff runs in a different thread or process from the gui. Not only is this natural separation of concerns, but also your gui wouldn't freeze. Moreover, you could then use the gui to interrupt or modify the behavior of the SNMP scan. And it makes it easier to put a different "gui" on it (like a command line interface.) In any case, mixing your gui code with your scanning code is going to make it hard to change either of them.