pkgsrc changes: - updating bundled modules * threads from 1.75 to 1.78 * threads::shared from 1.32 to 1.33 * Math::BigInt from 1.89_01 to 1.95 (without test merges) Upstream changes of avove modules >>> threads <<< 1.78 Wed Sep 22 17:21:22 2010 - Handle missing signal handler in thread (threads bug #60460) 1.77 Fri Mar 26 13:36:33 2010 - Fix race condition in t/threads.t (threads bug #55633) 1.76 Tue Mar 9 14:02:43 EST 2010 - Handle magic on arg to ->object() (bug #73330) - Make ->object(threads->tid()) work like ->self() (bug #73330) - Noted memory consumption issue in POD - Added reusable thread pool example >>> threads::shared <<< 1.33 Tue Mar 9 14:03:47 EST 2010 - Handle shared object reference during global destruction - Document that changing array length via $#array doesn't work >>> Math::BigInt <<< 2010-09-03 v1.90 rafl * fix bnok() for k==0 and k==n-1 2010-09-10 v1.91 rafl * fix various documentation bugs 2010-09-10 v1.92 rafl * re-upload v1.91 with a fixed SIGNATURE 2010-09-13 v1.93 rafl * Depend on perl >= 5.6.2 * Remove obsolete core test directory boilerplate * Convert from Test to Test::More 2010-09-13 v1.94 rafl DEVELOPMENT RELEASE * Attempt to fix Math::BigInt::Lite failures 2010-09-14 v1.95 rafl * Re-upload v1.94 as a stable release
608 lines
21 KiB
Text
608 lines
21 KiB
Text
$NetBSD: patch-dt,v 1.1 2010/09/23 21:47:48 sno Exp $
|
|
|
|
update of threads to 1.78
|
|
|
|
--- dist/threads/t/thread.t.orig 2010-09-06 23:30:32.000000000 +0000
|
|
+++ dist/threads/t/thread.t
|
|
@@ -20,7 +20,7 @@ BEGIN {
|
|
}
|
|
|
|
$| = 1;
|
|
- print("1..34\n"); ### Number of tests that will be run ###
|
|
+ print("1..35\n"); ### Number of tests that will be run ###
|
|
};
|
|
|
|
print("ok 1 - Loaded\n");
|
|
@@ -161,7 +161,7 @@ package main;
|
|
|
|
# bugid #24165
|
|
|
|
-run_perl(prog => 'use threads 1.75;' .
|
|
+run_perl(prog => 'use threads 1.78;' .
|
|
'sub a{threads->create(shift)} $t = a sub{};' .
|
|
'$t->tid; $t->join; $t->tid',
|
|
nolib => ($ENV{PERL_CORE}) ? 0 : 1,
|
|
@@ -304,6 +304,26 @@ SKIP: {
|
|
"counts of calls to DESTROY");
|
|
}
|
|
|
|
+# Bug 73330 - Apply magic to arg to ->object()
|
|
+{
|
|
+ my @tids :shared;
|
|
+
|
|
+ my $thr = threads->create(sub {
|
|
+ lock(@tids);
|
|
+ push(@tids, threads->tid());
|
|
+ cond_signal(@tids);
|
|
+ });
|
|
+
|
|
+ {
|
|
+ lock(@tids);
|
|
+ cond_wait(@tids) while (! @tids);
|
|
+ }
|
|
+
|
|
+ ok(threads->object($_), 'Got threads object') foreach (@tids);
|
|
+
|
|
+ $thr->join();
|
|
+}
|
|
+
|
|
exit(0);
|
|
|
|
# EOF
|
|
--- dist/threads/t/exit.t.orig 2010-09-06 23:30:32.000000000 +0000
|
|
+++ dist/threads/t/exit.t
|
|
@@ -48,7 +48,7 @@ my $rc = $thr->join();
|
|
ok(! defined($rc), 'Exited: threads->exit()');
|
|
|
|
|
|
-run_perl(prog => 'use threads 1.75;' .
|
|
+run_perl(prog => 'use threads 1.78;' .
|
|
'threads->exit(86);' .
|
|
'exit(99);',
|
|
nolib => ($ENV{PERL_CORE}) ? 0 : 1,
|
|
@@ -98,7 +98,7 @@ $rc = $thr->join();
|
|
ok(! defined($rc), 'Exited: $thr->set_thread_exit_only');
|
|
|
|
|
|
-run_perl(prog => 'use threads 1.75 qw(exit thread_only);' .
|
|
+run_perl(prog => 'use threads 1.78 qw(exit thread_only);' .
|
|
'threads->create(sub { exit(99); })->join();' .
|
|
'exit(86);',
|
|
nolib => ($ENV{PERL_CORE}) ? 0 : 1,
|
|
@@ -108,7 +108,7 @@ run_perl(prog => 'use threads 1.75 qw(ex
|
|
is($?>>8, 86, "'use threads 'exit' => 'thread_only'");
|
|
}
|
|
|
|
-my $out = run_perl(prog => 'use threads 1.75;' .
|
|
+my $out = run_perl(prog => 'use threads 1.78;' .
|
|
'threads->create(sub {' .
|
|
' exit(99);' .
|
|
'});' .
|
|
@@ -124,7 +124,7 @@ my $out = run_perl(prog => 'use threads
|
|
like($out, '1 finished and unjoined', "exit(status) in thread");
|
|
|
|
|
|
-$out = run_perl(prog => 'use threads 1.75 qw(exit thread_only);' .
|
|
+$out = run_perl(prog => 'use threads 1.78 qw(exit thread_only);' .
|
|
'threads->create(sub {' .
|
|
' threads->set_thread_exit_only(0);' .
|
|
' exit(99);' .
|
|
@@ -141,7 +141,7 @@ $out = run_perl(prog => 'use threads 1.7
|
|
like($out, '1 finished and unjoined', "set_thread_exit_only(0)");
|
|
|
|
|
|
-run_perl(prog => 'use threads 1.75;' .
|
|
+run_perl(prog => 'use threads 1.78;' .
|
|
'threads->create(sub {' .
|
|
' $SIG{__WARN__} = sub { exit(99); };' .
|
|
' die();' .
|
|
--- dist/threads/t/basic.t.orig 2010-09-06 23:30:32.000000000 +0000
|
|
+++ dist/threads/t/basic.t
|
|
@@ -27,7 +27,7 @@ sub ok {
|
|
|
|
BEGIN {
|
|
$| = 1;
|
|
- print("1..33\n"); ### Number of tests that will be run ###
|
|
+ print("1..34\n"); ### Number of tests that will be run ###
|
|
};
|
|
|
|
use threads;
|
|
@@ -153,14 +153,17 @@ $thrx = threads->object();
|
|
ok(30, ! defined($thrx), 'No object');
|
|
$thrx = threads->object(undef);
|
|
ok(31, ! defined($thrx), 'No object');
|
|
-$thrx = threads->object(0);
|
|
-ok(32, ! defined($thrx), 'No object');
|
|
|
|
threads->import('stringify');
|
|
$thr1 = threads->create(sub {});
|
|
-ok(33, "$thr1" eq $thr1->tid(), 'Stringify');
|
|
+ok(32, "$thr1" eq $thr1->tid(), 'Stringify');
|
|
$thr1->join();
|
|
|
|
+# ->object($tid) works like ->self() when $tid is thread's TID
|
|
+$thrx = threads->object(threads->tid());
|
|
+ok(33, defined($thrx), 'Main thread object');
|
|
+ok(34, 0 == $thrx->tid(), "Check so that tid for threads work for main thread");
|
|
+
|
|
exit(0);
|
|
|
|
# EOF
|
|
--- dist/threads/threads.xs.orig 2010-09-06 23:30:32.000000000 +0000
|
|
+++ dist/threads/threads.xs
|
|
@@ -52,7 +52,7 @@ typedef perl_os_thread pthread_t;
|
|
|
|
/* Values for 'state' member */
|
|
#define PERL_ITHR_DETACHED 1 /* Thread has been detached */
|
|
-#define PERL_ITHR_JOINED 2 /* Thread has been joined */
|
|
+#define PERL_ITHR_JOINED 2 /* Thread is being / has been joined */
|
|
#define PERL_ITHR_FINISHED 4 /* Thread has finished execution */
|
|
#define PERL_ITHR_THREAD_EXIT_ONLY 8 /* exit() only exits current thread */
|
|
#define PERL_ITHR_NONVIABLE 16 /* Thread creation failed */
|
|
@@ -71,7 +71,7 @@ typedef struct _ithread {
|
|
int state; /* Detached, joined, finished, etc. */
|
|
int gimme; /* Context of create */
|
|
SV *init_function; /* Code to run */
|
|
- SV *params; /* Args to pass function */
|
|
+ AV *params; /* Args to pass function */
|
|
#ifdef WIN32
|
|
DWORD thr; /* OS's idea if thread id */
|
|
HANDLE handle; /* OS's waitable handle */
|
|
@@ -215,7 +215,7 @@ S_ithread_clear(pTHX_ ithread *thread)
|
|
S_ithread_set(aTHX_ thread);
|
|
|
|
SvREFCNT_dec(thread->params);
|
|
- thread->params = Nullsv;
|
|
+ thread->params = NULL;
|
|
|
|
if (thread->err) {
|
|
SvREFCNT_dec(thread->err);
|
|
@@ -487,7 +487,7 @@ S_ithread_run(void * arg)
|
|
PL_perl_destruct_level = 2;
|
|
|
|
{
|
|
- AV *params = (AV *)SvRV(thread->params);
|
|
+ AV *params = thread->params;
|
|
int len = (int)av_len(params)+1;
|
|
int ii;
|
|
|
|
@@ -675,10 +675,13 @@ S_ithread_create(
|
|
IV stack_size,
|
|
int gimme,
|
|
int exit_opt,
|
|
- SV *params)
|
|
+ SV **params_start,
|
|
+ SV **params_end)
|
|
{
|
|
ithread *thread;
|
|
ithread *current_thread = S_ithread_get(aTHX);
|
|
+ AV *params;
|
|
+ SV **array;
|
|
|
|
#if PERL_VERSION <= 8 && PERL_SUBVERSION <= 7
|
|
SV **tmps_tmp = PL_tmps_stack;
|
|
@@ -781,7 +784,7 @@ S_ithread_create(
|
|
* they are created
|
|
*/
|
|
SvREFCNT_dec(PL_endav);
|
|
- PL_endav = newAV();
|
|
+ PL_endav = NULL;
|
|
|
|
clone_param.flags = 0;
|
|
if (SvPOK(init_function)) {
|
|
@@ -792,8 +795,13 @@ S_ithread_create(
|
|
SvREFCNT_inc(sv_dup(init_function, &clone_param));
|
|
}
|
|
|
|
- thread->params = sv_dup(params, &clone_param);
|
|
- SvREFCNT_inc_void(thread->params);
|
|
+ thread->params = params = newAV();
|
|
+ av_extend(params, params_end - params_start - 1);
|
|
+ AvFILLp(params) = params_end - params_start - 1;
|
|
+ array = AvARRAY(params);
|
|
+ while (params_start < params_end) {
|
|
+ *array++ = SvREFCNT_inc(sv_dup(*params_start++, &clone_param));
|
|
+ }
|
|
|
|
#if PERL_VERSION <= 8 && PERL_SUBVERSION <= 7
|
|
/* The code below checks that anything living on the tmps stack and
|
|
@@ -908,7 +916,6 @@ S_ithread_create(
|
|
#endif
|
|
/* Must unlock mutex for destruct call */
|
|
MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
|
|
- sv_2mortal(params);
|
|
thread->state |= PERL_ITHR_NONVIABLE;
|
|
S_ithread_free(aTHX_ thread); /* Releases MUTEX */
|
|
#ifndef WIN32
|
|
@@ -924,7 +931,6 @@ S_ithread_create(
|
|
}
|
|
|
|
MY_POOL.running_threads++;
|
|
- sv_2mortal(params);
|
|
return (thread);
|
|
}
|
|
|
|
@@ -942,7 +948,6 @@ ithread_create(...)
|
|
char *classname;
|
|
ithread *thread;
|
|
SV *function_to_call;
|
|
- AV *params;
|
|
HV *specs;
|
|
IV stack_size;
|
|
int context;
|
|
@@ -950,7 +955,8 @@ ithread_create(...)
|
|
SV *thread_exit_only;
|
|
char *str;
|
|
int idx;
|
|
- int ii;
|
|
+ SV **args_start;
|
|
+ SV **args_end;
|
|
dMY_POOL;
|
|
CODE:
|
|
if ((items >= 2) && SvROK(ST(1)) && SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
|
|
@@ -988,18 +994,19 @@ ithread_create(...)
|
|
|
|
context = -1;
|
|
if (specs) {
|
|
+ SV **svp;
|
|
/* stack_size */
|
|
- if (hv_exists(specs, "stack", 5)) {
|
|
- stack_size = SvIV(*hv_fetch(specs, "stack", 5, 0));
|
|
- } else if (hv_exists(specs, "stacksize", 9)) {
|
|
- stack_size = SvIV(*hv_fetch(specs, "stacksize", 9, 0));
|
|
- } else if (hv_exists(specs, "stack_size", 10)) {
|
|
- stack_size = SvIV(*hv_fetch(specs, "stack_size", 10, 0));
|
|
+ if ((svp = hv_fetch(specs, "stack", 5, 0))) {
|
|
+ stack_size = SvIV(*svp);
|
|
+ } else if ((svp = hv_fetch(specs, "stacksize", 9, 0))) {
|
|
+ stack_size = SvIV(*svp);
|
|
+ } else if ((svp = hv_fetch(specs, "stack_size", 10, 0))) {
|
|
+ stack_size = SvIV(*svp);
|
|
}
|
|
|
|
/* context */
|
|
- if (hv_exists(specs, "context", 7)) {
|
|
- str = (char *)SvPV_nolen(*hv_fetch(specs, "context", 7, 0));
|
|
+ if ((svp = hv_fetch(specs, "context", 7, 0))) {
|
|
+ str = (char *)SvPV_nolen(*svp);
|
|
switch (*str) {
|
|
case 'a':
|
|
case 'A':
|
|
@@ -1018,27 +1025,27 @@ ithread_create(...)
|
|
default:
|
|
Perl_croak(aTHX_ "Invalid context: %s", str);
|
|
}
|
|
- } else if (hv_exists(specs, "array", 5)) {
|
|
- if (SvTRUE(*hv_fetch(specs, "array", 5, 0))) {
|
|
+ } else if ((svp = hv_fetch(specs, "array", 5, 0))) {
|
|
+ if (SvTRUE(*svp)) {
|
|
context = G_ARRAY;
|
|
}
|
|
- } else if (hv_exists(specs, "list", 4)) {
|
|
- if (SvTRUE(*hv_fetch(specs, "list", 4, 0))) {
|
|
+ } else if ((svp = hv_fetch(specs, "list", 4, 0))) {
|
|
+ if (SvTRUE(*svp)) {
|
|
context = G_ARRAY;
|
|
}
|
|
- } else if (hv_exists(specs, "scalar", 6)) {
|
|
- if (SvTRUE(*hv_fetch(specs, "scalar", 6, 0))) {
|
|
+ } else if ((svp = hv_fetch(specs, "scalar", 6, 0))) {
|
|
+ if (SvTRUE(*svp)) {
|
|
context = G_SCALAR;
|
|
}
|
|
- } else if (hv_exists(specs, "void", 4)) {
|
|
- if (SvTRUE(*hv_fetch(specs, "void", 4, 0))) {
|
|
+ } else if ((svp = hv_fetch(specs, "void", 4, 0))) {
|
|
+ if (SvTRUE(*svp)) {
|
|
context = G_VOID;
|
|
}
|
|
}
|
|
|
|
/* exit => thread_only */
|
|
- if (hv_exists(specs, "exit", 4)) {
|
|
- str = (char *)SvPV_nolen(*hv_fetch(specs, "exit", 4, 0));
|
|
+ if ((svp = hv_fetch(specs, "exit", 4, 0))) {
|
|
+ str = (char *)SvPV_nolen(*svp);
|
|
exit_opt = (*str == 't' || *str == 'T')
|
|
? PERL_ITHR_THREAD_EXIT_ONLY : 0;
|
|
}
|
|
@@ -1050,11 +1057,11 @@ ithread_create(...)
|
|
}
|
|
|
|
/* Function args */
|
|
- params = newAV();
|
|
+ args_start = &ST(idx + 2);
|
|
if (items > 2) {
|
|
- for (ii=2; ii < items ; ii++) {
|
|
- av_push(params, SvREFCNT_inc(ST(idx+ii)));
|
|
- }
|
|
+ args_end = &ST(idx + items);
|
|
+ } else {
|
|
+ args_end = args_start;
|
|
}
|
|
|
|
/* Create thread */
|
|
@@ -1063,7 +1070,8 @@ ithread_create(...)
|
|
stack_size,
|
|
context,
|
|
exit_opt,
|
|
- newRV_noinc((SV*)params));
|
|
+ args_start,
|
|
+ args_end);
|
|
if (! thread) {
|
|
XSRETURN_UNDEF; /* Mutex already unlocked */
|
|
}
|
|
@@ -1236,7 +1244,7 @@ ithread_join(...)
|
|
PerlInterpreter *other_perl;
|
|
CLONE_PARAMS clone_params;
|
|
|
|
- params_copy = (AV *)SvRV(thread->params);
|
|
+ params_copy = thread->params;
|
|
other_perl = thread->interp;
|
|
clone_params.stashes = newAV();
|
|
clone_params.flags = CLONEf_JOIN_IN;
|
|
@@ -1337,6 +1345,7 @@ ithread_kill(...)
|
|
ithread *thread;
|
|
char *sig_name;
|
|
IV signal;
|
|
+ int no_handler = 1;
|
|
CODE:
|
|
/* Must have safe signals */
|
|
if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG) {
|
|
@@ -1366,11 +1375,21 @@ ithread_kill(...)
|
|
MUTEX_LOCK(&thread->mutex);
|
|
if (thread->interp) {
|
|
dTHXa(thread->interp);
|
|
- PL_psig_pend[signal]++;
|
|
- PL_sig_pending = 1;
|
|
+ if (PL_psig_pend && PL_psig_ptr[signal]) {
|
|
+ PL_psig_pend[signal]++;
|
|
+ PL_sig_pending = 1;
|
|
+ no_handler = 0;
|
|
+ }
|
|
+ } else {
|
|
+ /* Ignore signal to terminated thread */
|
|
+ no_handler = 0;
|
|
}
|
|
MUTEX_UNLOCK(&thread->mutex);
|
|
|
|
+ if (no_handler) {
|
|
+ Perl_croak(aTHX_ "Signal %s received in thread %"UVuf", but no signal handler set.", sig_name, thread->tid);
|
|
+ }
|
|
+
|
|
/* Return the thread to allow for method chaining */
|
|
ST(0) = ST(0);
|
|
/* XSRETURN(1); - implied */
|
|
@@ -1409,6 +1428,7 @@ void
|
|
ithread_object(...)
|
|
PREINIT:
|
|
char *classname;
|
|
+ SV *arg;
|
|
UV tid;
|
|
ithread *thread;
|
|
int state;
|
|
@@ -1421,34 +1441,47 @@ ithread_object(...)
|
|
}
|
|
classname = (char *)SvPV_nolen(ST(0));
|
|
|
|
- if ((items < 2) || ! SvOK(ST(1))) {
|
|
+ /* Turn $tid from PVLV to SV if needed (bug #73330) */
|
|
+ arg = ST(1);
|
|
+ SvGETMAGIC(arg);
|
|
+
|
|
+ if ((items < 2) || ! SvOK(arg)) {
|
|
XSRETURN_UNDEF;
|
|
}
|
|
|
|
/* threads->object($tid) */
|
|
- tid = SvUV(ST(1));
|
|
+ tid = SvUV(arg);
|
|
|
|
- /* Walk through threads list */
|
|
- MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
|
|
- for (thread = MY_POOL.main_thread.next;
|
|
- thread != &MY_POOL.main_thread;
|
|
- thread = thread->next)
|
|
- {
|
|
- /* Look for TID */
|
|
- if (thread->tid == tid) {
|
|
- /* Ignore if detached or joined */
|
|
- MUTEX_LOCK(&thread->mutex);
|
|
- state = thread->state;
|
|
- MUTEX_UNLOCK(&thread->mutex);
|
|
- if (! (state & PERL_ITHR_UNCALLABLE)) {
|
|
- /* Put object on stack */
|
|
- ST(0) = sv_2mortal(S_ithread_to_SV(aTHX_ Nullsv, thread, classname, TRUE));
|
|
- have_obj = 1;
|
|
+ /* If current thread wants its own object, then behave the same as
|
|
+ ->self() */
|
|
+ thread = S_ithread_get(aTHX);
|
|
+ if (thread->tid == tid) {
|
|
+ ST(0) = sv_2mortal(S_ithread_to_SV(aTHX_ Nullsv, thread, classname, TRUE));
|
|
+ have_obj = 1;
|
|
+
|
|
+ } else {
|
|
+ /* Walk through threads list */
|
|
+ MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
|
|
+ for (thread = MY_POOL.main_thread.next;
|
|
+ thread != &MY_POOL.main_thread;
|
|
+ thread = thread->next)
|
|
+ {
|
|
+ /* Look for TID */
|
|
+ if (thread->tid == tid) {
|
|
+ /* Ignore if detached or joined */
|
|
+ MUTEX_LOCK(&thread->mutex);
|
|
+ state = thread->state;
|
|
+ MUTEX_UNLOCK(&thread->mutex);
|
|
+ if (! (state & PERL_ITHR_UNCALLABLE)) {
|
|
+ /* Put object on stack */
|
|
+ ST(0) = sv_2mortal(S_ithread_to_SV(aTHX_ Nullsv, thread, classname, TRUE));
|
|
+ have_obj = 1;
|
|
+ }
|
|
+ break;
|
|
}
|
|
- break;
|
|
}
|
|
+ MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
|
|
}
|
|
- MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
|
|
|
|
if (! have_obj) {
|
|
XSRETURN_UNDEF;
|
|
--- dist/threads/threads.pm.orig 2010-09-06 23:30:32.000000000 +0000
|
|
+++ dist/threads/threads.pm
|
|
@@ -5,7 +5,7 @@ use 5.008;
|
|
use strict;
|
|
use warnings;
|
|
|
|
-our $VERSION = '1.75';
|
|
+our $VERSION = '1.78';
|
|
my $XS_VERSION = $VERSION;
|
|
$VERSION = eval $VERSION;
|
|
|
|
@@ -134,7 +134,7 @@ threads - Perl interpreter-based threads
|
|
|
|
=head1 VERSION
|
|
|
|
-This document describes threads version 1.75
|
|
+This document describes threads version 1.78
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
@@ -361,9 +361,10 @@ key) will cause its ID to be used as the
|
|
=item threads->object($tid)
|
|
|
|
This will return the I<threads> object for the I<active> thread associated
|
|
-with the specified thread ID. Returns C<undef> if there is no thread
|
|
-associated with the TID, if the thread is joined or detached, if no TID is
|
|
-specified or if the specified TID is undef.
|
|
+with the specified thread ID. If C<$tid> is the value for the current thread,
|
|
+then this call works the same as C<-E<gt>self()>. Otherwise, returns C<undef>
|
|
+if there is no thread associated with the TID, if the thread is joined or
|
|
+detached, if no TID is specified or if the specified TID is undef.
|
|
|
|
=item threads->yield()
|
|
|
|
@@ -902,6 +903,18 @@ other threads are started afterwards.
|
|
If the above does not work, or is not adequate for your application, then file
|
|
a bug report on L<http://rt.cpan.org/Public/> against the problematic module.
|
|
|
|
+=item Memory consumption
|
|
+
|
|
+On most systems, frequent and continual creation and destruction of threads
|
|
+can lead to ever-increasing growth in the memory footprint of the Perl
|
|
+interpreter. While it is simple to just launch threads and then
|
|
+C<-E<gt>join()> or C<-E<gt>detach()> them, for long-lived applications, it is
|
|
+better to maintain a pool of threads, and to reuse them for the work needed,
|
|
+using L<queues|Thread::Queue> to notify threads of pending work. The CPAN
|
|
+distribution of this module contains a simple example
|
|
+(F<examples/pool_reuse.pl>) illustrating the creation, use and monitoring of a
|
|
+pool of I<reusable> threads.
|
|
+
|
|
=item Current working directory
|
|
|
|
On all platforms except MSWin32, the setting for the current working directory
|
|
@@ -975,7 +988,7 @@ involved, you may be able to work around
|
|
version of the object (e.g., using L<Data::Dumper> or L<Storable>), and then
|
|
reconstituting it in the joining thread. If you're using Perl 5.10.0 or
|
|
later, and if the class supports L<shared objects|threads::shared/"OBJECTS">,
|
|
-you can pass them via L<shared queues| Thread::Queue>.
|
|
+you can pass them via L<shared queues|Thread::Queue>.
|
|
|
|
=item END blocks in threads
|
|
|
|
@@ -992,6 +1005,12 @@ mutexes that are needed to control funct
|
|
For this reason, the use of C<END> blocks in threads is B<strongly>
|
|
discouraged.
|
|
|
|
+=item Open directory handles
|
|
+
|
|
+Spawning threads with open directory handles (see
|
|
+L<opendir|perlfunc/"opendir DIRHANDLE,EXPR">) will crash the interpreter.
|
|
+L<[perl #75154]|http://rt.perl.org/rt3/Public/Bug/Display.html?id=75154>
|
|
+
|
|
=item Perl Bugs and the CPAN Version of L<threads>
|
|
|
|
Support for threads extends beyond the code in this module (i.e.,
|
|
@@ -1021,7 +1040,7 @@ L<threads> Discussion Forum on CPAN:
|
|
L<http://www.cpanforum.com/dist/threads>
|
|
|
|
Annotated POD for L<threads>:
|
|
-L<http://annocpan.org/~JDHEDDEN/threads-1.75/threads.pm>
|
|
+L<http://annocpan.org/~JDHEDDEN/threads-1.78/threads.pm>
|
|
|
|
Source repository:
|
|
L<http://code.google.com/p/threads-shared/>
|
|
--- /dev/null
|
|
+++ dist/threads/t/kill2.t
|
|
--- /dev/null 2010-09-23 21:51:28.000000000 +0200
|
|
+++ dist/threads/t/kill2.t 2010-09-23 21:47:56.000000000 +0200
|
|
@@ -0,0 +1,68 @@
|
|
+use strict;
|
|
+use warnings;
|
|
+
|
|
+BEGIN {
|
|
+ require($ENV{PERL_CORE} ? '../../t/test.pl' : './t/test.pl');
|
|
+
|
|
+ use Config;
|
|
+ if (! $Config{'useithreads'}) {
|
|
+ skip_all(q/Perl not compiled with 'useithreads'/);
|
|
+ }
|
|
+}
|
|
+
|
|
+use ExtUtils::testlib;
|
|
+
|
|
+use threads;
|
|
+
|
|
+BEGIN {
|
|
+ $| = 1;
|
|
+ print("1..3\n"); ### Number of tests that will be run ###
|
|
+};
|
|
+
|
|
+fresh_perl_is(<<'EOI', 'ok', { }, 'No signal handler in thread');
|
|
+ use threads;
|
|
+ my $test = sub {
|
|
+ while(1) { sleep(1) }
|
|
+ };
|
|
+ my $thr = threads->create($test);
|
|
+ threads->yield();
|
|
+ $thr->detach();
|
|
+ eval {
|
|
+ $thr->kill('STOP');
|
|
+ };
|
|
+ print(($@ =~ /no signal handler set/) ? 'ok' : 'not ok');
|
|
+EOI
|
|
+
|
|
+fresh_perl_is(<<'EOI', 'ok', { }, 'Handler to signal mismatch');
|
|
+ use threads;
|
|
+ my $test = sub {
|
|
+ $SIG{'TERM'} = sub { threads->exit() };
|
|
+ while(1) { sleep(1) }
|
|
+ };
|
|
+ my $thr = threads->create($test);
|
|
+ threads->yield();
|
|
+ $thr->detach();
|
|
+ eval {
|
|
+ $thr->kill('STOP');
|
|
+ };
|
|
+ print(($@ =~ /no signal handler set/) ? 'ok' : 'not ok');
|
|
+EOI
|
|
+
|
|
+fresh_perl_is(<<'EOI', 'ok', { }, 'Handler and signal match');
|
|
+ use threads;
|
|
+ my $test = sub {
|
|
+ $SIG{'STOP'} = sub { threads->exit() };
|
|
+ while(1) { sleep(1) }
|
|
+ };
|
|
+ my $thr = threads->create($test);
|
|
+ threads->yield();
|
|
+ $thr->detach();
|
|
+ eval {
|
|
+ $thr->kill('STOP');
|
|
+ };
|
|
+ print((! $@) ? 'ok' : 'not ok');
|
|
+EOI
|
|
+
|
|
+exit(0);
|
|
+
|
|
+# EOF
|