Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I kill Perl threads?

In this program I create a fork, and then call domultithreading from it. It then creates a few threads.

sub domultithreading {
    #Not my function
    my ($num) = @_;
    my @thrs;
    my $i = 0;
    my $connectionsperthread = 50;
    while ( $i < $num ) {
        $thrs[$i] = threads->create( \&doconnections, $connectionsperthread, 1 );
        $i += $connectionsperthread;
    }
    my @threadslist = threads->list();
    while ( $#threadslist > 0 ) {
        $failed = 0;
    }
}

sub kill {
    #how can I kill the threads made in domultithreading?
    kill 9, $pid;
    print "\nkilling $pid\n";
}

I then want to be able to kill the fork and its threads, however I can't figure it out. Any suggestions?

Thanks a lot

like image 747
bag-man Avatar asked May 03 '26 09:05

bag-man


2 Answers

Perl provides two concurrency models: Processes and Threads. While you shouldn't neccessarily mix these two without a good reason, threads do model processes quite closely, so we can nearly treat them as such. Specifically, we can send signals to threads.

Processes can be signalled with the kill function: kill SIGNAL => $pid, while threads can be signalled with the kill method: $thr->kill(SIGNAL). This method returns the thread object. Signals can be intercepted when setting signal handlers in the %SIG hash.

This means that every process TERM signal handler TERMs all the child threads like

 $_->kill(9)->join() for threads->list;

and every thread TERM signal handler simply exits the thread, or does cleaning up:

 threads->exit; # exit the current thread
like image 121
amon Avatar answered May 06 '26 07:05

amon


There are actually few different ways to kill a thread in Perl, depending on what you want to achieve.

Let's take the following code as example:

use strict;
use warnings;
use threads;
use Thread::Queue;

# Create the shared queue (used by the threads):
my $queue = Thread::Queue->new();

sub main {    
    # Initialise the shared queue:
    $queue->enqueue("A", "B", "C", "D", "E", "F");
    print "Total number of items: " . $queue->pending() . "\n";
    $queue->end();  # signal that there is no more work to be sent...

    # Create 3 threads:  
    threads->create('do') for ( 0..2 );
    print "Number of current threads: " . threads->list() . "\n";

    foreach my $thread ( threads->list() ) {  # for each thread...
        $thread->join();  # wait the thread to finish all its work...

        print "Number of items in the queue: " . $queue->pending() . "\n" if defined $queue->pending();
        print "Number of current threads: " . threads->list() . "\n";
    }
}

sub do {
    # Retrieve the current thread ID:
    my $threadID = threads->self()->tid();

    # Setup the thread's kill signal handler:
    local $SIG{KILL} = sub { threads->exit() };

    while ( defined (my $item = $queue->dequeue()) ) {  # for each element in the queue...
        print "(Thread-" . $threadID . "): Do something with item '$item'...\n";
        sleep 1 + $threadID;
        print "(Thread-" . $threadID . "): Finished to use item '$item'...\n";
    }
}


main();

The code above spawns 3 threads, each of which will take and process an element of the shared queue till the queue is empty.

In this case, since we declared that no more element will be added to the queue (i.e. $queue->end()), the threads will be joined (to the main) once they had processed all the elements of the queue. Indeed, using $thread->join() we are saying to the main to wait for $thread to join.

If we omit to declare $queue->end(), the threads will not join the main but stay pending for new elements of the queue.

Now, if we want to kill the threads, we have two options: killing the threads but letting them to finish what they are doing first or simply (brutally) killing the threads immediately. In Perl, both are achieved via Thread Signalling.

In the first case (i.e. if we want to tell the threads to finish their work and, after, to stop processing the shared queue), we should use $thread->kill('KILL')->join():

foreach my $thread ( threads->list() ) {  # for each thread...
    $thread->kill('KILL')->join();  # wait the thread finish its work and kill it...

    print "Number of items in the queue: " . $queue->pending() . "\n" if defined $queue->pending();
    print "Number of current threads: " . threads->list() . "\n";
}

On the other hand, in the latter case (i.e. if we want to kill the threads immediately), we should use $thread->kill('KILL')->kill():

foreach my $thread ( threads->list() ) {  # for each thread...
    $thread->kill('KILL')->kill();  # kill the thread immediately...

    print "Number of items in the queue: " . $queue->pending() . "\n" if defined $queue->pending();
    print "Number of current threads: " . threads->list() . "\n";
}

Of course, if you want to kill the thread from within itself, you just need to call threads->exit() or simply use return:

sub do {
    ...
    threads->exit();  # kill the thread...
    ...
}
like image 22
Paolo Rovelli Avatar answered May 06 '26 07:05

Paolo Rovelli



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!