📄 kill.t
字号:
use strict;use warnings;BEGIN { if ($ENV{'PERL_CORE'}){ chdir 't'; unshift @INC, '../lib'; } use Config; if (! $Config{'useithreads'}) { print("1..0 # Skip: Perl not compiled with 'useithreads'\n"); exit(0); }}use ExtUtils::testlib;use threads;BEGIN { eval { require threads::shared; threads::shared->import(); }; if ($@ || ! $threads::shared::threads_shared) { print("1..0 # Skip: threads::shared not available\n"); exit(0); } local $SIG{'HUP'} = sub {}; my $thr = threads->create(sub {}); eval { $thr->kill('HUP') }; $thr->join(); if ($@ && $@ =~ /safe signals/) { print("1..0 # Skip: Not using safe signals\n"); exit(0); } require Thread::Queue; require Thread::Semaphore; $| = 1; print("1..18\n"); ### Number of tests that will be run ###};my $q = Thread::Queue->new();my $TEST = 1;sub ok{ $q->enqueue(@_); while ($q->pending()) { my $ok = $q->dequeue(); my $name = $q->dequeue(); my $id = $TEST++; if ($ok) { print("ok $id - $name\n"); } else { print("not ok $id - $name\n"); printf("# Failed test at line %d\n", (caller)[2]); } }}### Start of Testing ###ok(1, 'Loaded');### Thread cancel #### Set up to capture warning when thread terminatesmy @errs :shared;$SIG{__WARN__} = sub { push(@errs, @_); };sub thr_func { my $q = shift; # Thread 'cancellation' signal handler $SIG{'KILL'} = sub { $q->enqueue(1, 'Thread received signal'); die("Thread killed\n"); }; # Thread sleeps until signalled $q->enqueue(1, 'Thread sleeping'); sleep(1) for (1..10); # Should not go past here $q->enqueue(0, 'Thread terminated normally'); return ('ERROR');}# Create threadmy $thr = threads->create('thr_func', $q);ok($thr && $thr->tid() == 2, 'Created thread');threads->yield();sleep(1);# Signal threadok($thr->kill('KILL') == $thr, 'Signalled thread');threads->yield();# Cleanupmy $rc = $thr->join();ok(! $rc, 'No thread return value');# Check for thread termination messageok(@errs && $errs[0] =~ /Thread killed/, 'Thread termination warning');### Thread suspend/resume ###sub thr_func2{ my $q = shift; my $sema = shift; $q->enqueue($sema, 'Thread received semaphore'); # Set up the signal handler for suspension/resumption $SIG{'STOP'} = sub { $q->enqueue(1, 'Thread suspending'); $sema->down(); $q->enqueue(1, 'Thread resuming'); $sema->up(); }; # Set up the signal handler for graceful termination my $term = 0; $SIG{'TERM'} = sub { $q->enqueue(1, 'Thread caught termination signal'); $term = 1; }; # Do work until signalled to terminate while (! $term) { sleep(1); } $q->enqueue(1, 'Thread done'); return ('OKAY');}# Create a semaphore for use in suspending the threadmy $sema = Thread::Semaphore->new();ok($sema, 'Semaphore created');# Create a thread and send it the semaphore$thr = threads->create('thr_func2', $q, $sema);ok($thr && $thr->tid() == 3, 'Created thread');threads->yield();sleep(1);# Suspend the thread$sema->down();ok($thr->kill('STOP') == $thr, 'Suspended thread');threads->yield();sleep(1);# Allow the thread to continue$sema->up();threads->yield();sleep(1);# Terminate the threadok($thr->kill('TERM') == $thr, 'Signalled thread to terminate');$rc = $thr->join();ok($rc eq 'OKAY', 'Thread return value');ok($thr->kill('TERM') == $thr, 'Ignore signal to terminated thread');# EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -