]> 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 3257b26847c9fb471753de15a9433e6f5355c7b2..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
@@ -523,27 +551,12 @@ STATIC void indirect_map_delete(pTHX_ const OP *o) {
 
 /* --- Check functions ----------------------------------------------------- */
 
-STATIC STRLEN indirect_nextline(const char *s, STRLEN len) {
- STRLEN i;
-
- for (i = 0; i < len; ++i) {
-  if (s[i] == '\n') {
-   ++i;
-   while (i < len && s[i] == '\r')
-    ++i;
-   break;
-  }
- }
-
- return i;
-}
-
 STATIC int indirect_find(pTHX_ SV *name_sv, const char *line_bufptr, STRLEN *name_pos) {
 #define indirect_find(NSV, LBP, NP) indirect_find(aTHX_ (NSV), (LBP), (NP))
  STRLEN      name_len, line_len;
  const char *name, *name_end;
  const char *line, *line_end;
- const char *p, *t, *u;
+ const char *p;
 
  line     = SvPV_const(PL_linestr, line_len);
  line_end = line + line_len;
@@ -572,26 +585,7 @@ STATIC int indirect_find(pTHX_ SV *name_sv, const char *line_bufptr, STRLEN *nam
    ++p;
  }
 
- t = line;
- u = t;
-
- /* If we're inside a string-like environment, we don't need to be smart for
-  * finding the positions of the tokens : as the line number will always be
-  * the line where the string began (or at least I hope so), and the line
-  * buffer points to the beginning of the string (likewise), we can just take
-  * the offset in this string as the position. */
- if (!PL_lex_inwhat) {
-  while (t <= p) {
-   STRLEN i = indirect_nextline(t, line_len);
-   if (i >= line_len)
-    break;
-   u         = t;
-   t        += i;
-   line_len -= i;
-  }
- }
-
- *name_pos = p - u;
+ *name_pos = p - line;
 
  return 1;
 }
@@ -610,6 +604,26 @@ STATIC OP *indirect_ck_const(pTHX_ OP *o) {
    STRLEN pos;
 
    if (indirect_find(sv, PL_oldbufptr, &pos)) {
+    STRLEN len;
+
+    /* If the constant is equal to the current package name, try to look for
+     * a "__PACKAGE__" coming before what we got. We only need to check this
+     * 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 (PL_curstash
+        && len == (STRLEN) HvNAMELEN_get(PL_curstash)
+        && memcmp(SvPVX(sv), HvNAME_get(PL_curstash), len) == 0) {
+     STRLEN pos_pkg;
+     SV    *pkg = sv_newmortal();
+     sv_setpvn(pkg, "__PACKAGE__", sizeof("__PACKAGE__")-1);
+
+     if (indirect_find(pkg, PL_oldbufptr, &pos_pkg) && pos_pkg < pos) {
+      sv  = pkg;
+      pos = pos_pkg;
+     }
+    }
+
     indirect_map_store(o, pos, sv, CopLINE(&PL_compiling));
     return o;
    }
@@ -837,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)
@@ -919,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
  }
 
@@ -1005,6 +1021,7 @@ PROTOTYPE: DISABLE
 PREINIT:
  ptable *t;
  SV     *global_code_dup;
+ GV     *gv;
 PPCODE:
  {
   my_cxt_t ud;
@@ -1021,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