Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re: How to terminate threads that hang or never return?

by jdhedden (Deacon)
on Jun 02, 2006 at 18:16 UTC ( [id://553351]=note: print w/replies, xml ) Need Help??


in reply to How to terminate threads that hang or never return?

What can be done to kill the stray thead and warn the user that a thread has gone on to la-la-land? Is there a way to terminate this thread?
Threads cannot be cancelled directly. However, if you install threads v1.27 or higher (obtain the latest version from CPAN), you can send a signal to a thread so that it can then terminate itself (say by calling die). Be sure to read the caveats in the Thread Signalling section of the POD.

Here is a working example that should give you an idea of what you need to do:

#!/usr/bin/perl use strict; use warnings; no warnings 'threads'; use threads 1.27; use threads::shared; use Thread::Queue; ### Global Variables ### # Flag to inform all threads that application is terminating my $TERM :shared = 0; # Used for timing out threads my $TIMEOUT = 10; my $TIMER = Thread::Queue->new(); # Used by threads to signal that they are done my $DONE = Thread::Queue->new(); ### Signal Handling ### # Gracefully terminate application on ^C or 'kill' $SIG{'INT'} = $SIG{'TERM'} = sub { print(">>> Terminating <<<\n"); $TERM = 1; }; # This signal handler is called inside threads # that get cancelled by the timer thread $SIG{'KILL'} = sub { my $tid = threads->tid(); # Tell user we've been terminated printf(" %3d <- Killed\n", $tid); # Tell main thread that we're done $DONE->enqueue($tid); # Commit hari-kari die("Thread $tid killed\n"); }; ### Main Processing Section ### MAIN: { # Number of threads my $max_threads = (@ARGV) ? shift : 10; # Start timer thread threads->create('timer')->detach(); # Do lots of work while (! $TERM) { # Start max threads for (my $needed = $max_threads - threads->list(); $needed && ! $TERM; $needed--) { # New thread my $tid = threads->new(\&worker)->tid(); # Add to timer queue $TIMER->enqueue($tid, $TIMEOUT); } # Join with threads as they finish while (! monitor_threads()) { sleep(1); } } # Wait for threads to finish while ((threads->list() > 0) && $TIMEOUT--) { sleep(1); monitor_threads(); } # Kill and detach remaining threads foreach my $thr (threads->list()) { $thr->kill('KILL')->detach(); } sleep(1); # A moment of silence } print("Done\n"); exit(0); ### Thread Entry Point Subroutines ### # A worker thread sub worker { # My thread ID my $tid = threads->tid(); printf("Working -> %3d\n", $tid); # Do some work while monitoring $TERM my $sleep = 5 + int(rand(10)); while (($sleep > 0) && ! $TERM) { $sleep -= sleep($sleep); } # Tell user we're done printf(" %3d <- Finished\n", $tid); # Tell main thread that we're done $DONE->enqueue($tid); return; } # The timer thread that monitors other threads for timeout sub timer { my %timers; # Contains thread IDs and their remaining time # Loop until told to quit while (! $TERM) { # Check for new threads while (my $tid = $TIMER->dequeue_nb()) { # Decrement its timeout $timers{$tid} = $TIMER->dequeue() - 1; } sleep(1); # Check for timed out threads while (my ($tid, $timeout) = each(%timers)) { if ($timeout) { $timers{$tid}--; } else { # Cancel timed out threads, if still running if (my $thr = threads->object($tid)) { $thr->kill('KILL'); } delete($timers{$tid}); } } } } ### Helper Subroutines ### # Join to threads that have finished processing # Returns the number of threads joined sub monitor_threads { my $count = 0; while (my $tid = $DONE->dequeue_nb()) { threads->object($tid)->join(); $count++; } return ($count); }

Remember: There's always one more bug.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2024-04-18 15:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found