]> git.vpit.fr Git - perl/modules/indirect.git/blobdiff - indirect.xs
Nullify thread local storage entries when they are freed
[perl/modules/indirect.git] / indirect.xs
index 1cdd3eb090c2e52d8abdcd1c27b0be76f452c3b8..5cd420cb31f7897649bde1324dec1ea1d98706c6 100644 (file)
 # define HvNAMELEN_get(H) strlen(HvNAME_get(H))
 #endif
 
+#ifndef OP_SIBLING
+# define OP_SIBLING(O) ((O)->op_sibling)
+#endif
+
 #define I_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S))))))
 
 #if I_HAS_PERL(5, 10, 0) || defined(PL_parser)
@@ -319,16 +323,40 @@ STATIC void indirect_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) {
  ptable_hints_store(ud->tbl, ent->key, h2);
 }
 
-#include "reap.h"
-
 STATIC void indirect_thread_cleanup(pTHX_ void *ud) {
  dMY_CXT;
 
  SvREFCNT_dec(MY_CXT.global_code);
+ MY_CXT.global_code = NULL;
  ptable_free(MY_CXT.map);
+ MY_CXT.map = NULL;
  ptable_hints_free(MY_CXT.tbl);
+ MY_CXT.tbl = NULL;
+}
+
+STATIC int indirect_endav_free(pTHX_ SV *sv, MAGIC *mg) {
+ SAVEDESTRUCTOR_X(indirect_thread_cleanup, NULL);
+
+ return 0;
 }
 
+STATIC MGVTBL indirect_endav_vtbl = {
+ 0,
+ 0,
+ 0,
+ 0,
+ indirect_endav_free
+#if MGf_COPY
+ , 0
+#endif
+#if MGf_DUP
+ , 0
+#endif
+#if MGf_LOCAL
+ , 0
+#endif
+};
+
 #endif /* I_THREADSAFE */
 
 #if I_WORKAROUND_REQUIRE_PROPAGATION
@@ -583,7 +611,8 @@ STATIC OP *indirect_ck_const(pTHX_ OP *o) {
      * when we already had a match because __PACKAGE__ can only appear in
      * direct method calls ("new __PACKAGE__" is a syntax error). */
     len = SvCUR(sv);
-    if (len == (STRLEN) HvNAMELEN_get(PL_curstash)
+    if (PL_curstash
+        && len == (STRLEN) HvNAMELEN_get(PL_curstash)
         && memcmp(SvPVX(sv), HvNAME_get(PL_curstash), len) == 0) {
      STRLEN pos_pkg;
      SV    *pkg = sv_newmortal();
@@ -822,7 +851,7 @@ STATIC OP *indirect_ck_entersub(pTHX_ OP *o) {
     goto done;
    oop = lop->op_first;
   } while (oop->op_type != OP_PUSHMARK);
-  oop = oop->op_sibling;
+  oop = OP_SIBLING(oop);
   mop = lop->op_last;
 
   if (!oop)
@@ -904,8 +933,10 @@ STATIC void indirect_teardown(pTHX_ void *root) {
  {
   dMY_CXT;
   ptable_free(MY_CXT.map);
+  MY_CXT.map = NULL;
 #if I_THREADSAFE
   ptable_hints_free(MY_CXT.tbl);
+  MY_CXT.tbl = NULL;
 #endif
  }
 
@@ -990,6 +1021,7 @@ PROTOTYPE: DISABLE
 PREINIT:
  ptable *t;
  SV     *global_code_dup;
+ GV     *gv;
 PPCODE:
  {
   my_cxt_t ud;
@@ -1006,7 +1038,23 @@ PPCODE:
   MY_CXT.owner       = aTHX;
   MY_CXT.global_code = global_code_dup;
  }
- reap(3, indirect_thread_cleanup, NULL);
+ gv = gv_fetchpv(__PACKAGE__ "::_THREAD_CLEANUP", 0, SVt_PVCV);
+ if (gv) {
+  CV *cv = GvCV(gv);
+  if (!PL_endav)
+   PL_endav = newAV();
+  SvREFCNT_inc(cv);
+  if (!av_store(PL_endav, av_len(PL_endav) + 1, (SV *) cv))
+   SvREFCNT_dec(cv);
+  sv_magicext((SV *) PL_endav, NULL, PERL_MAGIC_ext, &indirect_endav_vtbl, NULL, 0);
+ }
+ XSRETURN(0);
+
+void
+_THREAD_CLEANUP(...)
+PROTOTYPE: DISABLE
+PPCODE:
+ indirect_thread_cleanup(aTHX_ NULL);
  XSRETURN(0);
 
 #endif