http://www.perlmonks.org?node_id=1007974

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

I have a question. I want to exit all threads when I issue a "die" command. The script involved is very old, and not well written. What I get is that even after using threads->exit(), PERL issues a warning saying:

Perl exited with active threads: 2 running and unjoined 0 finished and unjoined 0 running and detached
Any ideas? I expected the threads to exit.

Replies are listed 'Best First'.
Re: removing all threads..
by BrowserUk (Patriarch) on Dec 09, 2012 at 12:47 UTC

    You could add $_->join for threads::list(); just before the program ends; but it will require the threads to terminate before the program will end.

    Alternatively, if you do not care to wait for the threads to complete; detach the threads, either when you create them:

    threads->new( ... )->detach;

    Or just before you exit the program:

    $_->detach for threads::list(); sleep 1; exit;

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.

    RIP Neil Armstrong

Re: removing all threads..
by flexvault (Monsignor) on Dec 09, 2012 at 14:33 UTC

    ISAI student,

    Normally the existence of a file is not a good way for synchronization. But since you want to "remove all threads" anyway, you could have the 'die' routine create a file in a directory common to all threads, and then within each thread test for the existence of the file and if it exists then exit. This would work with 'fork' or separately started scripts as well.

    In the event that the process is going to restart 'immediately', then the master/startup script must ensure that all threads have completed before unlinking the file and restarting the process.

    Just a thought, don't use a counter for when to check. Use 'time' to check on the availability of the 'die' file. Check every 5-10 seconds or what is reasonable for your application. I would put a test like this just before waiting on a resource (socket, read, etc.). Also, don't put anything into the 'die' file, since then you could be setting up a potential race condition. If it matters what caused the 'die' then use a separate logging mechanism to record the event. You also may need to set an 'alarm' to break out of wait condition.

    Just some ideas!

    Good Luck...Ed

    "Well done is better than well said." - Benjamin Franklin

      Polling on a file is a ridiculous idea.

      If there is any need to poll -- and there usually isn't -- a simple shared variable is far simpler to program and far safer.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

      RIP Neil Armstrong

        I concur with this method, but I've found it difficult to do in the past without Threads::Shared which has some serious limitations. How else would you share a variable? I'm keenly interested in seeing your methodology...

        As far as the OP's question goes, In the past I've pushed the result of a new thread call onto an array, where I reap all the children on exit by coursing through the array and either waiting on them or sending them a nasty signal if necessary. Threads are tricky business... Especially when you're refactoring someone else's older code where they used threads irresponsibly, or at least without regard to how they get reaped.

        --
        Tommy
        $ perl -MMIME::Base64 -e 'print decode_base64 "YWNlQHRvbW15YnV0bGVyLm1lCg=="'

        BrowserUk,

        Okay...Ed

        "Well done is better than well said." - Benjamin Franklin

Re: removing all threads..
by zentara (Archbishop) on Dec 10, 2012 at 11:08 UTC
    Since the script is old, you could try putting this code block at the end of your existing main code.
    while( (scalar threads->list) > 0 ){ print scalar threads->list,"\n"; sleep 1; foreach my $thread (threads->list) { if( $thread->is_joinable ){ $thread->join;} } }
    You also should look at the old code, and see if die or exit is used anywhere. If any thread calls die or exit, it will bring down the whole program with your warning issued, which is harmless. However, you might want to put this in your code
    use threads ( 'exit' => 'threads_only');

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh