Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Suppressing thread warnings

by lennysan (Novice)
on Oct 10, 2008 at 17:09 UTC ( [id://716491]=perlquestion: print w/replies, xml ) Need Help??

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

When using threads, and not waiting for all of the threads to join, I get a message "A thread exited while 3 threads were running." I'd like to suppress this warning. I realize it's best practice to join them, but that isn't an option in this case unfortunately. I just want to clean up logs that currently have tons of these warnings showing up all the time. Here is a simple app that creates this warning:
#!/usr/bin/perl use threads; my $thread1 = new threads(\&my_sub); my $thread2 = new threads(\&my_sub); sub my_sub {}

Replies are listed 'Best First'.
Re: Suppressing thread warnings
by BrowserUk (Patriarch) on Oct 10, 2008 at 17:51 UTC

    It's dumb that blasted message cannot be disabled! Same with the 'Free to wrong pool' developer diagnostic.

    The simplest solution is:

    use POSIX qw[ _exit ]; _exit( 123 );

    But be aware that no destructors will be called, so if anything in your code requires cleanup, instigate it manually first. For example,

    undef $objectNeedingCleanup; _exit( 123 );

    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.
      This did the job! Can you please explain what this actually does? I want to make sure it doesn't negatively affect my app. Note that it exists at the end of each run, so I'm not worried about garbage collection over a long period.

        POSIX::_exit() calls your C-runtime to terminate the process. That bypasses all Perl contructs including END{} blocks and DESTROY() subroutines. Effectively, it completely bypasses Per's usual clean-up routines.

        In doing so, it bypasses the perl-core code that detects that there are still threads running and produces the warning. But, it can also give problems if you are using modules that use DESTROY subs or END blocks to persist data, flush buffers and the like.

        You can often cause object DESTROY methods to be called by undefing the handles, but I don't know of any way of forcing END blocks to be run without going through the full perl clean-up process.

        In other words, use _exit() with caution.


        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.
Re: Suppressing thread warnings
by ikegami (Patriarch) on Oct 11, 2008 at 00:59 UTC

    For starters, one way to silence the warning (since threads 1.33?) is to detach the threads.

    #!/usr/bin/perl use threads; threads->new(\&my_sub)->detach(); threads->new(\&my_sub)->detach(); sub my_sub {}
    >perl script.pl >

    All it does is silence the warning. The underlying cause is still present, and it's quite serious. Your threads are being forcibly exited, doing no cleanup whatsoever. For example, the following code produces two empty files.

    #!/usr/bin/perl use threads; sub my_sub { open(my $fh, '>', "$0.".threads->tid() ) or die; print $fh 'text'; sleep(10); } threads->new(\&my_sub)->detach(); threads->new(\&my_sub)->detach(); sleep(2);

    If you wish to run your program in the background, either do it from the shell

    $ script.pl & unix
    >start /b "" script.pl Windows

    or using something like:

    #!/usr/bin/perl use strict; use warnings; BEGIN { # Move to running in background. if (!@ARGV || $ARGV[0] ne '--nobkg') { $SIG{CHLD} = 'IGNORE'; require IPC::Open3; IPC::Open3::open3( '<&STDIN', '>&STDOUT', '>&STDERR', $^X, $0, '--nobkg', @ARGV ); exit; } } use threads; sub my_sub { open(my $fh, '>', "$0.".threads->tid() ) or die; print $fh 'text'; sleep(10); } my $thread1 = new threads(\&my_sub); my $thread2 = new threads(\&my_sub); $_->join() for $thread1, $thread2;
      For starters, one way to silence the warning (since threads 1.33?) is to detach the threads.

      All very well if you *never* need to join the threads, but if, for example, you normally want to join them (to retrieve their results), but want to be able to terminate the process quickly without waiting for them if you receive a SIGTERM, you're stuffed.

      You can't even use the costly and nearly useless $thr->kill( <SIG> ) mechanism to pass on the signal, because it won't interupt IO, sort, etc. So, you're forced to either:

      • enable unsafe signals and risk crashing the entire process when you signal a thread.

      • use event-driven techniques--non-blocking IO; breaking code into iddy-biddy chunks--to ensure that your threads are periodically in a position to receive the signals.

        In which case you might as well just check a shared flag.

      • use _exit()

        Whilst it has risks, they are mostly mitigatable, and at least you control when things happen.

      These messages are entirely configurable and should be user controllable. Just another case of module authors deciding that they know better than module users.

      If you wish to run your program in the background, ...

      Where did that come from? Are you party to information not in the OP?


      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.

        All very well if you *never* need to join the threads, but if, for example, you normally want to join them (to retrieve their results), but want to be able to terminate the process quickly without waiting for them if you receive a SIGTERM, you're stuffed.

        My testing shows that exiting due to SIGTERM doesn't produce the warning. The process is simply killed. That means you can detach just before existing to silence the warning. Something like following should do the trick:

        END { $_->detach() for threads->list(); }

        If you wish to run your program in the background, ...

        Where did that come from? Are you party to information not in the OP?

        I got the idea that he wanted the threads to continue since he didn't end them. Obviously not the case. I should have provided assistance in ending his threads instead.

Re: Suppressing thread warnings
by SankoR (Prior) on Oct 10, 2008 at 17:25 UTC
    The warnings pragma has a threads category, so maybe...
    use strict; use warnings; no warnings qw[threads]; use threads; my $thread1 = new threads(\&my_sub); my $thread2 = new threads(\&my_sub); sub my_sub {} exit; # needs explicit exit for reasons beyond me
    It's been a while since I tangled with threads, but the above quiets the warnings with 5.10 on Win32.

    Addendum: See also the "WARNINGS" section of the threads.pm documentation.
      This didn't suppress this specific warning :(

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (3)
As of 2024-04-25 05:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found