maa has asked for the wisdom of the Perl Monks concerning the following question:
UPDATE: The answer is here. Dunno why I missed it!
Hi,
In order to try and speed up large overnight tasks (collect info from 1000+ PCs then update a database) I have been experimenting with fork.
My problem is twofold... If I try to share a database connection created with my $db=new Win32::ODBC($dsn); between threads then Perl crashes with a memory exception. (ActiveState 5.6.1 build 626)...
If I create a new connection in each thread I get conection number 0... and then nothing happens when methods execute. They behave as though they are working, though.
My test code is here... 123 lines.
#!C:/Activeperl/bin/perl.exe use strict; use warnings; use Win32::ODBC; $RODB::DSN='FORK'; #DSN for ODBC connection my @PIDS = (); my $x=0; #open (OUT,">C:/Temp/fork.log") or die("Can't open logfile $!\n"); #*STDOUT=*OUT; ##BEGIN_TEST## #This works my $db=DBConnect() or die("Can't connect to database.\n"); print "Test connection to database is: " . $db->Connection . "\n"; $db->Sql ("Insert into Computers Values('Test','This is a test.')") +; my @Tables=$db->TableList(''); if (@Tables) { foreach (@Tables) { print "$_\n"; } } #DBClose($db); ##END_TEST## my @computers = (<DATA>); print "Files open... PID $$ is going to start forking shortly.\n\n"; LOOP: foreach my $rbos (@computers) { chomp($rbos); print "$$ This computer is $rbos and \$x==$x\n"; my $pid = fork(); #Try to fork. push @PIDS, $pid; #Save the PID? if ($pid) { $x++; print "$$ Got PID $pid from fork()\n"; #Take a small break# sleep(3); undef $pid; if ($x == 10 ) { print "\$x made it to ten! Killing children.\n"; killkids(@PIDS); $x=0; } }else { print "\t$$ looking at $rbos\n"; my $db=DBConnect() or die("Can't create DB connection.\n"); + print "\t$$ DB Connection " . $db->Connection . "\n"; + #Weird behaviour when 'sleep(2)' is removed above. my $message=is_on($rbos); my $sql="INSERT INTO Computers (Computername,Message) VA +LUES ('$rbos','$message')"; print "\t$$ $sql\n"; print "\t$$ $message ... Updating DB... "; if ($db->Sql($sql) ) { print "failed.\n". $db->Error . "\n"; }else{ print "ok\n"; } DBClose($db); exit(); } } sleep(10); killkids(@PIDS); print STDERR "Done\n"; #------------ SUBS ---------------# sub killkids { my (@ids)=@_; print "$$ killkids has (" . (1+$#ids) . ") ids to kill\n"; for(@ids) {print "$$ killing $_\n"; kill($_); } } sub DBConnect { #print "Trying to connect to DB using DSN=${RODB::DSN}\n"; return (new Win32::ODBC($RODB::DSN)); } sub DBClose { return -1 if not defined(my $db=$_[0]); return $db->Close(); } sub is_on { my $pingcmd = "c:\\winnt\\system32\\ping.exe -n 2" ; my $pc = $_[0]; #Only expect 1 argument. my $ans = `$pingcmd $pc`; return 0 if ($ans =~ /Bad/ ); if ($ans =~ /bytes=32/) { if ($pc =~ /(\d+\.){3}\d+/ ) { return $pc; }else { return get_ipaddr($ans) } } return -1 ; } sub get_ipaddr { my $ans = $_[0]; #Only expect 1 string argument. $ans =~ s/[\w\W]*\[// ; #Strip everything up to "[" on result $ans =~ s/\].*//s ; #Strip everything after "]" on result return $ans ; } __DATA__ CNTR035533 RBOS207911 RBOS-DSM RBOS214876
Apart from not doing anything useful after the fork() it works ok... until I remove the sleep() on line 44. Then my IP address variables get clobbered - further reading obviously requried there on my part.
Does anyone have any ideas why the Win32::ODBC gives be a bum connection?
TIA - Mark
|
|---|