Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re^3: Advanced GUI with threads

by glenn (Scribe)
on Sep 13, 2013 at 15:09 UTC ( [id://1053956]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Advanced GUI with threads
in thread Advanced GUI with threads -working

Plz try latest code, w/strict and warnings. Not much more can be removed or simplified. Thank you for taking a look.
use XML::Simple; use Data::Dumper; use Sys::Hostname; use Tk; use Tk::DialogBox; use Tk::ColorEditor; use Tk::BrowseEntry; use Tk::LabEntry; use Tk::Pane; use threads; use threads::shared; use Thread::Semaphore; use Thread::Queue; use strict; use warnings; my $running : shared = 1; my $xs = new XML::Simple(keeproot=>1, forcearray=>1); my $SYSTEMJOB = $xs->XMLin("<systemlist></systemlist>"); my $sourcepath = "c:\\eyerobot\\"; my $reportpath = $sourcepath."Report\\"; my $matrixnanotestcount = "72"; my $matrixnanoruntime = "3600"; my $ver = "6.0"; my @config_options = ("none"); my $CLI = "/usr/AmiNas/cli"; #start threads my $addsys = Thread::Queue->new(); my $test_start = Thread::Queue->new(); my $test_done = Thread::Queue->new(); threads->create("executejob")->detach(); #dequeue test_start #create test system(s) for (my $x = 1; $x <= 1; $x++) { my $newsys = $xs->XMLin("<system></system>"); my $system = $newsys->{system}->[0]; my $passwd = "password"; my $license = "none"; my $tag = "Global"; my $config = "unknown"; my $raidtype = "unknown"; my $serial = "unknown"; my $servicekey = "unknown"; $serial = int(rand(899999999999999))+100000000000000; #TESTING VAL +UES $servicekey = int(rand(899999999999999))+100000000000000; #TESTING + VALUES my $hardware = "unknown"; my $macaddr1 = "unknown"; my $macaddr2 = "unknown"; my $cap = "unknown"; my $e = 0; #create XML structure $system->{ip}->[0] = int(rand(253)+1).".".int(rand(253)+1).".".int +(rand(253)+1).".".int(rand(253)+1); $system->{ip}->[1] = 0; $system->{hardware}->[0] = $hardware; $system->{volume}->[0] = ""; $system->{status}->[0] = "proceed"; #proceed, success, failure $system->{state}->[0] = "new"; #new, starting, running, paused, co +mplete, inaccessible $system->{reportpath}->[0] = "$reportpath"; $system->{health}->[0] = "unknown"; $system->{events}->[0] = "unknown"; $system->{serial}->[0] = $serial; $system->{servicekey}->[0] = $servicekey; $system->{createtime}->[0] = time; $system->{filename}->[0] = "unknown"; $system->{mac}->[0] = $macaddr1; $system->{mac}->[1] = $macaddr2; $system->{reasonforfailure}->[0] = "unknown"; $system->{password}->[0] = $passwd; $system->{license}->[0]->{option}->[0] = $license; $system->{license}->[0]->{result}->[0] = "unknown"; $system->{license}->[0]->{tag}->[0] = $tag; $system->{license}->[0]->{capacity}->[0] = "$cap"; $system->{license}->[0]->{jbods}->[0] = "$e"; $system->{raidtype}->[0] = "$raidtype"; $system->{customerConfig}->[0] = "$config"; $system->{customerConfig}->[1] = "unknown"; $system->{job}->[0]->{step}->[0] = "cleanupconfig"; $system->{job}->[0]->{step}->[1] = "PrintHardwareConfig"; $system->{job}->[0]->{nextjob}->[0] = "0:0"; #step:iteration (only + matrixnano has iterations) $system->{job}->[0]->{status}->[0] = "ready"; #ready, running, com +plete $system->{job}->[0]->{matrixnanoiterations}->[0] = "$matrixnanotes +tcount"; $system->{job}->[0]->{matrixnanoruntime}->[0] = "$matrixnanoruntim +e"; $system->{gui}->[0]->{but_ctl_1}->[0] = "Start"; $system->{gui}->[0]->{but_ctl_2}->[0] = "Pause"; $system->{gui}->[0]->{but_test_param}->[0] = "normal"; $system->{gui}->[0]->{progress}->[0] = "Not running"; $addsys->enqueue($newsys); } #user interface my @systems; testControl(); MainLoop(); $running = 0; exit 0; #THREADS sub executejob { $SIG{__DIE__} = sub{ tcrash(threads->tid()); }; while ($running) { #START AND DETACH TEST while ($test_start->pending() > 0) { my $system = $test_start->dequeue(); if ($system->{state}->[0] eq "running") { if ($system->{job}->[0]->{status}->[0] eq "ready") { $system->{job}->[0]->{status}->[0] = "running"; $system->{job}->[0]->{nextjob}->[0] =~ m/(\d+):(\d ++)/; my $test = $1; my $iteration = $2; my $testname = $system->{job}->[0]->{step}->[$test +]; #print "Starting test [$testname]\n"; threads->create(\&{$testname}, $system)->detach(); + #test } } } } sleep 1; } #GUI sub testControl { my $mainwindow = MainWindow->new(); $mainwindow->title("DIAG Test Control"); $mainwindow->configure(-background=> 'LightYellow'); $mainwindow->protocol('WM_DELETE_WINDOW',sub{$mainwindow->messageB +ox(-message=>"Window cannot be closed this way.", -title=>"Disabled") +;return;}); $mainwindow->Label(-text=>"DIAG Test Control [ver. $ver].", -backg +round=>'tan', -foreground=>'darkgreen', -font=>['courier', '14', 'bol +d'])->pack(-side => 'top'); my $lic_grid = $mainwindow->Scrolled('Frame', -background=> 'Light +Yellow', -scrollbars=>'se', -height=>'500', -width=>'1150', -padx=>'1 +0')->pack(-side => 'top'); $lic_grid->Label(-text=>"IP Address")->grid(-row=>1, -column=>0, - +sticky=>"nsew"); $lic_grid->Label(-text=>"Serial Number")->grid(-row=>1, -column=>1 +, -sticky=>"nsew"); $lic_grid->Label(-text=>"License")->grid(-row=>1, -column=>2, -sti +cky=>"nsew"); $lic_grid->Label(-text=>"Configuration")->grid(-row=>1, -column=>3 +, -sticky=>"nsew"); $lic_grid->Label(-text=>"Blink")->grid(-row=>1, -column=>4, -stick +y=>"nsew"); $lic_grid->Label(-text=>"Matrixnano\nIterations")->grid(-row=>1, - +column=>5, -columnspan=>3, -sticky=>"nsew"); $lic_grid->Label(-text=>"Matrixnano Run Time")->grid(-row=>1, -col +umn=>8, -columnspan=>9, -sticky=>"nsew"); $lic_grid->Label(-text=>"Test Time")->grid(-row=>1, -column=>17, - +sticky=>"nsew"); $lic_grid->Label(-text=>"System\nStatus")->grid(-row=>1, -column=> +18, -sticky=>"nsew"); $lic_grid->Label(-text=>"System\nStatus")->grid(-row=>1, -column=> +19, -sticky=>"nsew"); $lic_grid->Label(-text=>"Controls")->grid(-row=>1, -column=>20, -c +olumnspan=>2, -sticky=>"nsew"); $lic_grid->Label(-text=>"Progress")->grid(-row=>1, -column=>22, -s +ticky=>"nsew"); my $loop_running = $mainwindow->repeat(5000, sub { if ($running == 0) { $mainwindow->destroy; } }); #HELP HERE my $loop_collect = $mainwindow->repeat(1000, sub { #PROCESS COMPLETED TEST RESULTS #MUST BE HERE TO UPDATE GLOBAL VAR #THIS SHOULD UPDATE GUI LABELS ON THE RIGHT SIDE FOR THE SYSTE +M while ($test_done->pending() > 0) { print "Getting results of test. Have [".$test_done->pendin +g()."] to process.\n"; my $results = $test_done->dequeue(); for (my $count = 0; $count < @{$SYSTEMJOB->{systemlist}->[ +0]->{system}}; $count++) { my $system = $SYSTEMJOB->{systemlist}->[0]->{system}-> +[$count]; if ($system->{servicekey}->[0] eq $results->{serviceke +y}->[0]) { #receive results if ($results->{status}->[0] !~ m/fail/i) { #stop/pause if ($system->{state}->[0] eq "stopping") { $results->{state}->[0] = "stopped"; $results->{job}->[0]->{nextjob}->[0] = "0: +0"; } elsif ($system->{state}->[0] eq "pausing") { $results->{state}->[0] = "paused"; } #set next test my ($test, $iteration) = split(":", $results-> +{job}->[0]->{nextjob}->[0]); print "Finished [$test]\n"; if ($results->{job}->[0]->{step}->[$test] eq " +domatrixnano") { $iteration++; if ($iteration > $results->{job}->[0]->{ma +trixnanoiterations}->[0]) { $test++; $iteration=0; } } else { $test++; $iteration=0; } print "Next test is [$test] out of a total of +[".@{$results->{job}->[0]->{step}}."] tests.\n"; if ($test >= @{$results->{job}->[0]->{step}}) +{ print "DONE\n"; $results->{job}->[0]->{nextjob}->[0] = "DO +NE"; $results->{job}->[0]->{status}->[0] = "com +plete"; $results->{state}->[0] = "complete"; } else { print "NEXT\n"; $results->{job}->[0]->{nextjob}->[0] = "$t +est:$iteration"; $results->{job}->[0]->{status}->[0] = "rea +dy"; } } else { $results->{job}->[0]->{status}->[0] = "complet +e"; } $system = $results; print "System State: ".$system->{state}->[0]."\n"; $test_start->enqueue($system); last; } } $mainwindow->update(); } }); my $loop_addsys = $mainwindow->repeat(1000, sub{ while ($addsys->pending() > 0) { if (defined $SYSTEMJOB->{systemlist}->[0]->{system}) { if (@{$SYSTEMJOB->{systemlist}->[0]->{system}} > 125) +{ #Reserve some DATA IPs for DIAG controller last; } } #ADD NEW SYSTEM TO GUI my @test_cfg_options; my $newsys = $addsys->dequeue(); push(@{$SYSTEMJOB->{systemlist}->[0]->{system}}, $newsys-> +{system}->[0]); print "System count: ".@{$SYSTEMJOB->{systemlist}->[0]->{s +ystem}}."\n"; my $system = $SYSTEMJOB->{systemlist}->[0]->{system}->[@{$ +SYSTEMJOB->{systemlist}->[0]->{system}} - 1]; $system->{ip}->[1] = find_free_ip(); if (defined $system->{canister}) { $system->{alias}->[0] = find_free_ip(); } my $row = @{$SYSTEMJOB->{systemlist}->[0]->{system}} + 2; my $bgcolor="cornsilk"; if ($row % 2 == 0) { $bgcolor="LemonChiffon"; } $lic_grid->Label(-text=>$system->{ip}->[0], -background=>$ +bgcolor."1")->grid(-row=>$row, -column=>0, -sticky=>"nsew"); push(@test_cfg_options, $lic_grid->Entry(-textvariable=>\$ +system->{serial}->[0], -background=>$bgcolor."2", -width=>16, -highli +ghtthickness=>2, -highlightcolor=>'blue')->grid(-row=>$row, -column=> +1, -sticky=>"nsew")); $lic_grid->Button(-text=>"Set License", -background=>$bgco +lor."3", -command=>[\&LicenseOptions, $system->{license}->[0]])->grid +(-row=>$row, -column=>2, -sticky=>"nsew"); $lic_grid->Optionmenu(-variable=>\$system->{customerConfig +}->[0], -background=>$bgcolor."3", -options=>\@config_options)->grid( +-row=>$row, -column=>3, -sticky=>"nsew"); my $but_blink = $lic_grid->Button(-text=>"Blink Unit", -ba +ckground=>$bgcolor."4", -command=>sub{ async{ if ($system->{raidtype}->[0] =~ m/software/i or $s +ystem->{raidtype}->[0] =~ m/unknown/i) { my $output = qx"wincuri 2 $system->{ip}->[0] \ +"$CLI blink -t ld -l /dev/md255 raid\""; } if ($system->{raidtype}->[0] =~ m/hardware/i or $s +ystem->{raidtype}->[0] =~ m/unknown/i) { my $output = qx"wincuri 2 $system->{ip}->[0] \ +"$CLI blink -t ld -l /dev/sda raid\""; } }; })->grid(-row=>$row, -column=>4); if ($system->{raidtype}->[0] =~ m/none/i) { $but_blink->configure(-state => 'disabled'); } $lic_grid->Label(-text=>$system->{job}->[0]->{matrixnanoit +erations}->[0], -background=>$bgcolor."2", -width => 3)->grid(-row=>$ +row, -column=>5, -sticky=>"nsew"); push(@test_cfg_options, $lic_grid->Button(-text => "+", -b +ackground=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matrix +nanoiterations}->[0]++;})->grid(-row=>$row, -column=>6, -sticky=>"nse +w")); push(@test_cfg_options, $lic_grid->Button(-text => "-", -b +ackground=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matrix +nanoiterations}->[0]--;})->grid(-row=>$row, -column=>7, -sticky=>"nse +w")); $lic_grid->Label(-text=>$system->{job}->[0]->{matrixnanoru +ntime}->[0], -background=>$bgcolor."2", -width=>8)->grid(-row=>$row, +-column=>8, -sticky=>"nsew"); push(@test_cfg_options, $lic_grid->Button(-text => "+1D", +-background=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matr +ixnanoruntime}->[0]+=86400;})->grid(-row=>$row, -column=>9, -sticky=> +"nsew")); push(@test_cfg_options, $lic_grid->Button(-text => "-1D", +-background=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matr +ixnanoruntime}->[0]-=86400;if ($system->{job}->[0]->{matrixnanoruntim +e}->[0] < 0) {$system->{job}->[0]->{matrixnanoruntime}->[0] = 0;};})- +>grid(-row=>$row, -column=>10, -sticky=>"nsew")); push(@test_cfg_options, $lic_grid->Button(-text => "+1H", +-background=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matr +ixnanoruntime}->[0]+=3600;})->grid(-row=>$row, -column=>11, -sticky=> +"nsew")); push(@test_cfg_options, $lic_grid->Button(-text => "-1H", +-background=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matr +ixnanoruntime}->[0]-=3600;if ($system->{job}->[0]->{matrixnanoruntime +}->[0] < 0) {$system->{job}->[0]->{matrixnanoruntime}->[0] = 0;};})-> +grid(-row=>$row, -column=>12, -sticky=>"nsew")); push(@test_cfg_options, $lic_grid->Button(-text => "+5M", +-background=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matr +ixnanoruntime}->[0]+=300;})->grid(-row=>$row, -column=>13, -sticky=>" +nsew")); push(@test_cfg_options, $lic_grid->Button(-text => "-5M", +-background=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matr +ixnanoruntime}->[0]-=300;if ($system->{job}->[0]->{matrixnanoruntime} +->[0] < 0) {$system->{job}->[0]->{matrixnanoruntime}->[0] = 0;};})->g +rid(-row=>$row, -column=>14, -sticky=>"nsew")); push(@test_cfg_options, $lic_grid->Button(-text => "+5S", +-background=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matr +ixnanoruntime}->[0]+=5;})->grid(-row=>$row, -column=>15, -sticky=>"ns +ew")); push(@test_cfg_options, $lic_grid->Button(-text => "-5S", +-background=>$bgcolor."3", -command => sub{$system->{job}->[0]->{matr +ixnanoruntime}->[0]-=5;if ($system->{job}->[0]->{matrixnanoruntime}-> +[0] < 0) {$system->{job}->[0]->{matrixnanoruntime}->[0] = 0;};})->gri +d(-row=>$row, -column=>16, -sticky=>"nsew")); $lic_grid->Label(-textvariable=>\$system->{status}->[0], - +background=>$bgcolor."1")->grid(-row=>$row, -column=>18, -sticky=>"ns +ew"); #PROBLEM $lic_grid->Label(-textvariable=>\$system->{state}->[0], -b +ackground=>$bgcolor."1")->grid(-row=>$row, -column=>19, -sticky=>"nse +w"); #PROBLEM my $but_ctl_1 = $lic_grid->Button(-text=>"Start", -backgro +und=>$bgcolor."3", -state=>"normal", -foreground=>"black", -backgroun +d=>"green", -activeforeground=>"green", -activebackground=>"black")-> +grid(-row=>$row, -column=>20, -sticky=>"nsew"); my $but_ctl_2 = $lic_grid->Button(-text=>"Pause", -backgro +und=>$bgcolor."3", -state=>"disabled", -foreground=>"black", -backgro +und=>"yellow", -activeforeground=>"yellow", -activebackground=>"black +")->grid(-row=>$row, -column=>21, -sticky=>"nsew"); $lic_grid->Label(-textvariable=>\$system->{gui}->[0]->{pro +gress}->[0], -background=>$bgcolor."2", -width => 40)->grid(-row=>$ro +w, -column=>22, -sticky=>"nsew"); #PROBLEM $but_ctl_1->configure(-command=>sub{ my $state = $system->{state}->[0]; if ($state eq "new" or $state eq "stopped") { my @buttoncolor=("red","yellow"); $system->{state}->[0]="running"; foreach my $button (@test_cfg_options) { $button->configure(-state=>"disabled"); } $but_ctl_1->configure(-text=>"Stop", -foreground=> +"black", -background=>$buttoncolor[0], -activeforeground=>$buttoncolo +r[0], -activebackground=>"black"); $but_ctl_2->configure(-state=>"normal", -text=>"Pa +use", -foreground=>"black", -background=>$buttoncolor[1], -activefore +ground=>$buttoncolor[1], -activebackground=>"black"); $test_start->enqueue($system); } elsif ($state eq "paused") { my @buttoncolor=("green","yellow"); $system->{state}->[0]="stopped"; foreach my $button (@test_cfg_options) { $button->configure(-state=>"normal"); } $but_ctl_1->configure(-text=>"Start", -foreground= +>"black", -background=>$buttoncolor[0], -activeforeground=>$buttoncol +or[0], -activebackground=>"black"); $but_ctl_2->configure(-state=>"disabled", -text=>" +Pause",-foreground=>"black", -background=>$buttoncolor[1], -activefor +eground=>$buttoncolor[1], -activebackground=>"black"); } elsif ($state eq "running" or $state eq "pausing") { $mainwindow->messageBox(-message=>"Please wait for + the system to fully stop before making changes to the test paramater +s.", -title=>"Please Wait"); my @buttoncolor=("green","yellow"); $system->{state}->[0]="stopping"; foreach my $button (@test_cfg_options) { $button->configure(-state=>"normal"); } $but_ctl_1->configure(-text=>"Start", -foreground= +>"black", -background=>$buttoncolor[0], -activeforeground=>$buttoncol +or[0], -activebackground=>"black"); $but_ctl_2->configure(-state=>"disabled", -text=>" +Pause",-foreground=>"black", -background=>$buttoncolor[1], -activefor +eground=>$buttoncolor[1], -activebackground=>"black"); } elsif ($state eq "stopping") { $mainwindow->messageBox(-message=>"Please wait for + the system to fully stop. Once stopped you may make changes to the t +est paramaters.", -title=>"Please Wait"); } elsif ($state eq "complete") { $mainwindow->messageBox(-message=>"Please wait for + the system to fully stop. Once stopped you may make changes to the t +est paramaters.", -title=>"Please Wait"); } $mainwindow->update(); }); $but_ctl_2->configure(-command=>sub{ my $state = $system->{state}->[0]; if ($state eq "running") { my @buttoncolor=("red","green"); $system->{state}->[0]="pausing"; $but_ctl_1->configure(-text=>"Stop", -foreground=> +"black", -background=>$buttoncolor[0], -activeforeground=>$buttoncolo +r[0], -activebackground=>"black"); $but_ctl_2->configure(-text=>"Resume", -foreground +=>"black", -background=>$buttoncolor[1], -activeforeground=>$buttonco +lor[1], -activebackground=>"black"); } elsif ($state eq "paused") { my @buttoncolor=("red","yellow"); $system->{state}->[0]="running"; $but_ctl_1->configure(-text=>"Stop", -foreground=> +"black", -background=>$buttoncolor[0], -activeforeground=>$buttoncolo +r[0], -activebackground=>"black"); $but_ctl_2->configure(-text=>"Pause", -foreground= +>"black", -background=>$buttoncolor[1], -activeforeground=>$buttoncol +or[1], -activebackground=>"black"); $test_start->enqueue($system); } elsif ($state eq "pausing") { my @buttoncolor=("red","yellow"); $system->{state}->[0]="running"; $but_ctl_1->configure(-text=>"Stop", -foreground=> +"black", -background=>$buttoncolor[0], -activeforeground=>$buttoncolo +r[0], -activebackground=>"black"); $but_ctl_2->configure(-text=>"Pause", -foreground= +>"black", -background=>$buttoncolor[1], -activeforeground=>$buttoncol +or[1], -activebackground=>"black"); #race handle sleep 3; if ($system->{state}->[0] eq "paused") { $system->{state}->[0]="running"; $test_start->enqueue($system); } } $mainwindow->update(); }); }#end while }); $mainwindow->Button(-text=>"Finished", -background=>'tan', -comman +d=>sub {$mainwindow->destroy;})->pack(-side => 'top'); #$mainwindow->Button(-text=>"Finished", -background=>'tan', -comma +nd=>sub {quit();mainwindow->destroy;})->pack(-side => 'top'); } #SUBS sub convert_time ($) { my $time = $_[0]; my $days = int($time / 86400); $time -= ($days * 86400); my $hours = int($time / 3600); $time -= ($hours * 3600); my $minutes = int($time / 60); $time -= ($hours * 60); my $seconds = $time % 60; $days = $days .'d '; $hours = $hours .'h '; $minutes = $minutes . 'm '; return "$days $hours $minutes ${seconds}s"; } sub find_free_ip { for (my $ip = 2; $ip < 255; $ip++) { #0.1 is controller my $used = 0; for (my $s = 0; $s < @{$SYSTEMJOB->{systemlist}->[0]->{system} +}; $s++) { my $addr = $SYSTEMJOB->{systemlist}->[0]->{system}->[$s]-> +{ip}->[1]; my $alias = -1; if (defined $SYSTEMJOB->{systemlist}->[0]->{system}->[$s]- +>{alias}) { $alias = $SYSTEMJOB->{systemlist}->[0]->{system}->[$s] +->{alias}->[0]; } if ($ip == $addr or $ip == $alias) { $used = 1; last; } } if ($used == 0) { return "192.168.0.".$ip; } } return "OUT"; } sub tcrash { debugLogFunctionNameLineNum((caller(0))[2],(caller(1))[3]); my $tid = $_[0]; my $thr = threads->object($tid); my $error; if ($thr-error()) { $error = " due to error ". $thr->error(); } print "Thread ". (caller(1))[3] ." died at ". (caller(0))[2] ."$er +ror\n"; $running = 0; } sub debugLogFunctionNameLineNum { # Print sub header and caller info #debugLogFunctionNameLineNum((caller(0))[2],(caller(1))[3]); my ($callerline, $caller) = @_; unless ($caller) { $caller = "MAIN"; } if ($caller =~ m/eval/) { $caller = "Tk call"; $callerline = "Unknown"; } my $LineNumber = (caller(0))[2]; my $FunctionName = (caller(1))[3]; my $time = localtime time; unless ($FunctionName) { $FunctionName = "MAIN"; } print "$FunctionName, $LineNumber: Called from [$caller] at [$call +erline].\n"; } #TESTS sub cleanupconfig { my $subroutine = (caller(0))[3]; my $system = $_[0]; my $testtime = int(rand(30))+10; print "Running [$subroutine] [".$system->{state}->[0]."] for $test +time seconds\n"; print "Now that i am running the GUI should show the system state +as 'running', not 'new'.\n"; print "Progress should show the test name, not 'not running'\n"; sleep $testtime; print "[$subroutine] complete\n"; $test_done->enqueue($system); } sub PrintHardwareConfig { my $subroutine = (caller(0))[3]; my $system = $_[0]; my $testtime = int(rand(30))+5; print "Running [$subroutine] [".$system->{state}->[0]."] for $test +time seconds\n"; sleep $testtime; print "[$subroutine] complete\n"; $test_done->enqueue($system); }

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (9)
As of 2024-03-19 08:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found