Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

win32 threads problem

by leonidlm (Pilgrim)
on Dec 07, 2008 at 13:06 UTC ( [id://728700]=perlquestion: print w/replies, xml ) Need Help??

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

Hi All.
I am writing a perl program that will read a list of configuration files in a directory and open a separate thread for each file. This thread sub will open a UDP socket, send a special message, and wait TIMEOUT time for response. After opening all the threads I am waiting to all the threaded subs to finish. Here is a snippet of the code (In which I suspect I have a problem):
my @threads; my $thread; my $rc; while (@threads = threads->list()) { foreach $thread (@threads) { if ($thread->is_joinable()) { $rc = $thread->join(); # Send the opcmon # $rc->[0] is the return code. # $rc->[1] is the nodeName the thread worked on. &sendOpcmon($tag, $rc->[0], $rc->[1]); } } # To prevent the hard CPU lookups sleep(1); } # sub sendRequest { require IO::Socket::INET; #IO::Socket::INET->import(...); my ($msg, $peerAddr, $peerPort) = @_; my $eTime = time() + TIMEOUT; my $host = (split/\./, $msg)[0]; # configure the socket. $MySocket = new IO::Socket::INET->new( PeerPort => $peerPort, Proto => 'udp', PeerAddr => $peerAddr, ); ioctl($MySocket, 0x8004667e, pack("I", 1)); # Send the request. $MySocket->send($msg); # Now we will wait till the server will respond to our request. while(time() < $eTime) { $MySocket->recv($text,128); if($text =~ /OK/) { return [1, $host]; } # Sleep for 2 secs just to free up a %CPU usage sleep 2; } # We reached the timeout, probably no response will arrive. return [0, $host]; }
Unfortunately my code crashes the interpreter (in the $thread->join() call) with the error: "Free to wrong pool 1825cf0 not ff during global destruction".
I read some questions related to this issues here in the forum but unfortunately couldn't find a solution.
Can it be that IO::Socket::INET isn't threadsafe ?
If so, what is the best way to implement that ?

Replies are listed 'Best First'.
Re: win32 threads problem
by zentara (Archbishop) on Dec 07, 2008 at 14:41 UTC
    You don't show how/where you actually create your threads.

    I'm not really a human, but I play one on earth Remember How Lucky You Are
      Sorry, you are right. This code is just above the code I posted:
      # Open the configuration files directory and create a thread for each +configuration file opendir (CDIR, $cfgFilesDir) or die; my $file; my $thr; while ($file = readdir(CDIR)) { if ($file =~ /.+?\.properties/) { $thr = threads->create(\&sendRequest, $file, 'localhost', $pee +rPort ); } } closedir (CDIR);
Re: win32 threads problem
by BrowserUk (Patriarch) on Dec 07, 2008 at 16:27 UTC

    We could probably re-create something like your code from the snippets posted and the description, but it wouldn't be identical. And if we did, and it ran without error on our systems, and reported back that we couldn't reproduce the error you are getting, that wouldn't help you.

    And without you telling use which versions of perl, threads, threads::shared, IO:Socket and the rest you are using, the chances of us reproducing your particular problem are almost nil.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      The whole code:
      Declare the needed modules to import use IO::Socket::INET; use threads; use constant TIMEOUT => 5; # Bind arguments passed to the code to variables my $tag = shift; my $cfgFilesDir = shift; my $peerPort = shift; # Open the configuration files directory and create a thread for each +configuration file opendir (CDIR, $cfgFilesDir) or die; my $file; my $thr; while ($file = readdir(CDIR)) { if ($file =~ /.+?\.properties/) { $thr = threads->create(\&sendRequest, $file, 'localhost', $pee +rPort ); } } closedir (CDIR); # Wait till all the threads will finish their work. In the threads sub + I implemented a timeout # mechanism to prevent a infinity loop my @threads; my $thread; my $rc; while (@threads = threads->list()) { foreach $thread (@threads) { if ($thread->is_joinable()) { $rc = $thread->join(); # Send the opcmon # $rc->[0] is the return code. # $rc->[1] is the nodeName the thread worked on. &sendOpcmon($tag, $rc->[0], $rc->[1]); } } # To prevent the hard CPU lookups sleep(1); } # sub sendRequest { my ($msg, $peerAddr, $peerPort) = @_; my $eTime = time() + TIMEOUT; my $host = (split/\./, $msg)[0]; # configure the socket. $MySocket = new IO::Socket::INET->new( PeerPort => $peerPort, Proto => 'udp', PeerAddr => $peerAddr, ); ioctl($MySocket, 0x8004667e, pack("I", 1)); # Send the request. $MySocket->send($msg); # Now we will wait till the server will respond to our request. while(time() < $eTime) { $MySocket->recv($text,128); if($text =~ /OK/) { return [1, $host]; } # Sleep for 2 secs just to free up a %CPU usage sleep 2; } # We reached the timeout, probably no response will arrive. return [0, $host]; } # sub sendOpcmon { my ($tag, $val, $object) = @_; my $cmd = "opcmon $tag=$val -object $object"; #qx{$cmd}; print $cmd."\n"; }
      Module versions you requested:
      perl: v5.8.8 built for MSWin32-x86-multi-thread
      threads: 1.63
      IO:Socket:INET: 1.31
      (all the above modules where installed with the standard activePerl distribution)
      Hope that information will be enough. Thank you!

        I've succeeded in reproducing your error, and the problem turns out to be associated with opendir/readdir/closedir. Regardless of whether the you use globals or lexicals; or whether the directory handle is closed prior to spawning the threads, you get a trap when trying to join the threads. That doesn't make much sense to me, but there we are.

        I have a work around. Replace:

        opendir (CDIR, $cfgFilesDir) or die; my $file; my $thr; while ($file = readdir(CDIR)) { if ($file =~ /.+?\.properties/) { $thr = threads->create(\&sendRequest, $file, 'localhost', $pee +rPort ); } } closedir (CDIR);

        with

        while( my $file = <*.properties> ) { ## Check the glob matches your fi +les! my $thr = threads->create(\&sendRequest, $file, 'localhost', $peer +Port ); }

        And the global destruction problem will probably go away. At least it does here.

        There are other problems in your code that you'll discover if you enable strict.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        After modifying your program so it would run on linux, it dosn't throw an error, but I just connected to a server and printed the filename. You might want to simplify your program, like taking the thread create out of a loop and just create 3 threads, and see if it works. Also what windows version are you using? Older windows like ME don't handle Perl threads well.

        But the best thing to do is upgrade to Perl5.10 and see if it works there.


        I'm not really a human, but I play one on earth Remember How Lucky You Are

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2024-03-29 12:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found