PERL_GLOBAL_STRUCT threads issue
authorDavid Mitchell <davem@iabyn.com>
Tue, 8 Apr 2014 22:22:23 +0000 (23:22 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 9 Apr 2014 08:10:35 +0000 (09:10 +0100)
A test in op/threads.t roughly equivalent to this:

    use threads;
    sub f {};
    async \&f;

was randomly failing smokes under the combination of PERL_GLOBAL_STRUCT and
ASan.

This is due to the fact that, under PERL_GLOBAL_STRUCT, "global" vars
are actually allocated, and are freed as the very last thing before
exiting (later than perl_destruct()). In the code above, the created
thread is still exeecuting at this point, and so may access those "global"
vars.  ASan can detect that such a var is being accessed after being
freed; in this case due to PL_ppaddr being indexed in call_sv().

This is easily fixed using the PL_veto_cleanup mechanism; don't do those
final frees if there are still threads running.

util.c

index a5451c1..0a0ee40 100644 (file)
--- a/util.c
+++ b/util.c
@@ -4632,11 +4632,15 @@ Perl_init_global_struct(pTHX)
 void
 Perl_free_global_struct(pTHX_ struct perl_vars *plvarsp)
 {
+    int veto = plvarsp->Gveto_cleanup;
+
     PERL_ARGS_ASSERT_FREE_GLOBAL_STRUCT;
 # ifdef PERL_GLOBAL_STRUCT
 #  ifdef PERL_UNSET_VARS
     PERL_UNSET_VARS(plvarsp);
 #  endif
+    if (veto)
+        return;
     free(plvarsp->Gppaddr);
     free(plvarsp->Gcheck);
 #  ifdef PERL_GLOBAL_STRUCT_PRIVATE