From: Vincent Pit Date: Sat, 4 Oct 2014 22:54:33 +0000 (+0200) Subject: Do nothing after that the thread local storage has been freed X-Git-Tag: v0.13~5 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FLexical-Types.git;a=commitdiff_plain;h=cb00fbfded7c20f01c75b520c5e5d2b582e2d4be Do nothing after that the thread local storage has been freed This de facto disables the pragma for code eval'd during global destruction of a thread or a pseudo-fork. --- diff --git a/Types.xs b/Types.xs index 752e3f4..d37cdc7 100644 --- a/Types.xs +++ b/Types.xs @@ -348,7 +348,13 @@ get_enclosing_cv: STATIC SV *lt_tag(pTHX_ SV *value) { #define lt_tag(V) lt_tag(aTHX_ (V)) lt_hint_t *h; - SV *code = NULL; + SV *code = NULL; +#if LT_THREADSAFE + dMY_CXT; + + if (!MY_CXT.tbl) + return newSViv(0); +#endif /* LT_THREADSAFE */ if (SvROK(value)) { value = SvRV(value); @@ -369,13 +375,10 @@ STATIC SV *lt_tag(pTHX_ SV *value) { #endif /* !LT_HINT_STRUCT */ #if LT_THREADSAFE - { - dMY_CXT; - /* We only need for the key to be an unique tag for looking up the value later - * Allocated memory provides convenient unique identifiers, so that's why we - * use the hint as the key itself. */ - ptable_hints_store(MY_CXT.tbl, h, h); - } + /* We only need for the key to be an unique tag for looking up the value later + * Allocated memory provides convenient unique identifiers, so that's why we + * use the hint as the key itself. */ + ptable_hints_store(MY_CXT.tbl, h, h); #endif /* LT_THREADSAFE */ return newSViv(PTR2IV(h)); @@ -386,7 +389,10 @@ STATIC SV *lt_detag(pTHX_ const SV *hint) { lt_hint_t *h; #if LT_THREADSAFE dMY_CXT; -#endif + + if (!MY_CXT.tbl) + return NULL; +#endif /* LT_THREADSAFE */ if (!(hint && SvIOK(hint))) return NULL; @@ -710,7 +716,7 @@ STATIC OP *lt_ck_padany(pTHX_ OP *o) { if (stash && (code = lt_hint())) { dMY_CXT; SV *orig_pkg = newSVpvn(HvNAME_get(stash), HvNAMELEN_get(stash)); - SV *orig_meth = MY_CXT.default_meth; + SV *orig_meth = MY_CXT.default_meth; /* Guarded by lt_hint() */ SV *type_pkg = NULL; SV *type_meth = NULL; int items; @@ -914,9 +920,11 @@ STATIC void lt_peep(pTHX_ OP *o) { lt_old_peep(aTHX_ o); - ptable_seen_clear(seen); - lt_peep_rec(o); - ptable_seen_clear(seen); + if (seen) { + ptable_seen_clear(seen); + lt_peep_rec(o); + ptable_seen_clear(seen); + } } /* --- Interpreter setup/teardown ------------------------------------------ */ diff --git a/lib/Lexical/Types.pm b/lib/Lexical/Types.pm index 88b00af..518e205 100644 --- a/lib/Lexical/Types.pm +++ b/lib/Lexical/Types.pm @@ -269,6 +269,8 @@ The restrictions on the type (being either a defined package name or a constant) Only one mangler or prefix can be in use at the same time in a given scope. +Typed lexicals declarations that appear in code C'd during the global destruction phase of a spawned thread or pseudo-fork (the processes used internally for the C emulation on Windows) are ignored. + The implementation was tweaked to work around several limitations of vanilla C pragmas : it's thread safe, and doesn't suffer from a C bug that causes all pragmas to propagate into Cd scopes. With 5.8 perls, the pragma does not propagate into C. diff --git a/t/81-threads-teardown.t b/t/81-threads-teardown.t index c60e14f..7a5c227 100644 --- a/t/81-threads-teardown.t +++ b/t/81-threads-teardown.t @@ -7,7 +7,7 @@ use lib 't/lib'; use VPIT::TestHelpers; use Lexical::Types::TestThreads; -use Test::More tests => 1; +use Test::More tests => 2; { my $status = run_perl <<' RUN'; @@ -32,3 +32,21 @@ use Test::More tests => 1; RUN is $status, 0, 'loading the pragma in a thread and using it outside doesn\'t segfault'; } + +{ + my $status = run_perl <<' RUN'; + use threads; + BEGIN { require Lexical::Types; } + sub X::DESTROY { + eval 'use Lexical::Types; package Z; my Z $z = 1'; + exit 1 if $@; + } + threads->create(sub { + my $x = bless { }, 'X'; + $x->{self} = $x; + return; + })->join; + exit 0; + RUN + is $status, 0, 'Lexical::Types can be loaded in eval STRING during global destruction at the end of a thread'; +}