Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

using the thread->kill() feature on linux

by zentara (Archbishop)
on Oct 16, 2010 at 13:26 UTC ( [id://865662]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

The newer threads have a feature to send a signal to threads thru the syntax

# Send a signal to a thread $thr->kill('SIGUSR1');
Since killing threads was one of the trickiest parts of the older versions of the threads module, I was eager to test this out. But I'm getting segfaults and process crashes with the following simple test script. My Perl version is 5.12.2 with threads enabled.
#!/usr/bin/perl use warnings; use strict; use threads; print "I'm the parent pid-> $$\n"; my $thr = threads->new(\&sub1); my $thr1 = threads->new(\&sub2)->detach; for(1..15){ print "$_\n"; if( $_ == 5 ){ $thr->kill('SIGUSR1') } if( $_ == 10 ){ $thr1->kill('SIGKILL') } sleep 1; } exit; sub sub1{ # uncommenting the following stops the segfault # but still crashes the program #local $SIG{'SIGUSR1'} = sub{ print "yikes\n" }; my $myobject = threads->self; my $mytid= $myobject->tid; print "In the thread $myobject tid->$mytid \n"; my $count = 0; while(1){ $count++; print "\t\t\t$mytid -> $count"; sleep 1; } } sub sub2{ my $myobject = threads->self; my $mytid= $myobject->tid; print "In the thread $myobject tid->$mytid \n"; my $count = 0; while(1){ $count++; print "\t\t\t\t\t\t$mytid -> $count"; sleep 1; } }
So how would you successfully send a SIGKILL to a thread, so that only that target thread dies? Is it even possible?

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

Replies are listed 'Best First'.
Re: using the thread->kill() feature on linux
by BrowserUk (Patriarch) on Oct 16, 2010 at 16:00 UTC

    Personally, I think mixing signals and threads is a very bad idea, so I don't. But, maybe the following output from running your program on windows will give you some clues to your mistakes:

    c:\test>junk73 I'm the parent pid-> 4440 No such signal: SIGSIGUSR1 at C:\test\junk73.pl line 26. No such signal: SIGSIGUSR1 at C:\test\junk73.pl line 26. In the thread threads=SCALAR(0x35a9020) tid->1 1 In the thread threads=SCALAR(0x362daa8) tid->2 2 3 4 5 Unrecognized signal name: USR1 at C:\test\junk73.pl line 14. Perl exited with active threads: 1 running and unjoined 0 finished and unjoined 1 running and detached

    He he :)

    c:\test>perl -wE"$SIG{SIGSPUTNIK} = 'ignore'" No such signal: SIGSIGSPUTNIK at -e line 1.

    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: using the thread->kill() feature on linux
by zentara (Archbishop) on Oct 16, 2010 at 16:47 UTC
    Thanks for the pointers. This seems to work. I did notice that an error was raised when I tried to kill a detached thread, but joining after a kill seems to work. I still need to watch the memory cleanup, but I'm relieved that the basics are working.

    Works on linux. Notice the 'exit' => 'threads_only';

    #!/usr/bin/perl use warnings; use strict; use threads 'exit' => 'threads_only'; print "I'm the parent pid-> $$\n"; my $thr = threads->new(\&sub1); #my $thr1 = threads->new(\&sub2)->detach; # issues a warning on kill my $thr1 = threads->new(\&sub2); for(1..15){ print "$_\n"; if( $_ == 5 ){ $thr->kill('KILL')->join } if( $_ == 10 ){ $thr1->kill('KILL')->join } sleep 1; } exit; sub sub1{ my $myobject = threads->self; my $mytid= $myobject->tid; $SIG{'KILL'} = sub{ print "tid $mytid exiting\n"; threads->exit() }; print "In the thread $myobject tid->$mytid \n"; my $count = 0; while(1){ $count++; print "\t\t\t$mytid -> $count\n"; sleep 1; } } sub sub2{ my $myobject = threads->self; my $mytid= $myobject->tid; $SIG{'KILL'} = sub{ print "tid $mytid exiting\n"; threads->exit() }; print "In the thread $myobject tid->$mytid \n"; my $count = 0; while(1){ $count++; print "\t\t\t\t\t$mytid -> $count\n"; sleep 1; } }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: using the thread->kill() feature on linux
by BrowserUk (Patriarch) on Oct 16, 2010 at 17:09 UTC

    Which version of threads do you have? I just noticed these in the change log--maybe related?

    1.79 Fri Sep 24 18:40:59 2010 - Fix failing tests in t/kill2.t 1.78 Wed Sep 22 17:21:22 2010 - Handle missing signal handler in thread (threads bug #60460)

    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.
      My version is the stock module that came with Perl 5.12.2, which is 1.75.

      However, it seems to be working for me now; although I may be skirting around the bugs. :-)


      I'm not really a human, but I play one on earth.
      Old Perl Programmer Haiku ................... flash japh
Re: using the thread->kill() feature on linux
by dasgar (Priest) on Oct 16, 2010 at 16:09 UTC

    I'm not really an expert on using signals, but I recently was looking into something like this myself on Windows. If you look into the documentation on thread signaling, you'll need to add a signal handler such as the code below taken verbatim from that documentation.

    sub thr_func { # Thread 'cancellation' signal handler $SIG{'KILL'} = sub { threads->exit(); }; ... }

    One word of caution about the code above. It will detach the thread, not "kill" it. I presume that when you say when you want a thread to die, you want it to completely stop what it's doing and to go away. A detached thread won't release its memory until the main code exits out. For me, that was a critical point since I was trying to write code that was intended to run forever and collect and record data every 15 minutes.

      A detached thread won't release its memory until the main code exits out.

      Um. That's simply not true. Detached threads release their memory as soon as they terminate.

      This is clearly demonstrated here. I start 100 threads that sleep for 3 seconds. I wait a second to ensure they are all running and then check the process memory usage, which stands at 59MB.

      I then wait another 5 seconds to ensure they all end, and check memory again. It's now 25MB.

      #! perl -slw use strict; use threads; sub checkmem { print qx[ tasklist /nh /fi "pid eq $$"]; } async(sub{ sleep 3 })->detach for 1 .. 100; sleep 1; checkmem; sleep 5; checkmem; __END__ c:\test>junk74 perl.exe 4928 Console 1 58 +,960 K perl.exe 4928 Console 1 24 +,696 K

      Not all the memory is released back to the OS--indeed, on some systems maybe none of it will be--but it has been released back to the process memory pool for re-use.

      Non-detached threads don't release their memory until joined, but detached thread release it as soon as they exit the thread sub.

      If you think you have code where this doesn't happen, please post it and we can work out what you're doing wrong.


      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.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2024-04-26 08:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found