]> git.vpit.fr Git - perl/modules/Variable-Magic.git/commitdiff
Reference count vmg_op_name_len
authorVincent Pit <vince@profvince.com>
Sat, 14 Feb 2009 15:31:09 +0000 (16:31 +0100)
committerVincent Pit <vince@profvince.com>
Sat, 14 Feb 2009 15:34:58 +0000 (16:34 +0100)
Its refcnt is incremented when a wizard with op_info => NAME is created, and
decremented in the destructor of those wizards. This fixes segfaults that happen
when magic with op_info => NAME is casted onto a stash and not dispelled before
END time.

Magic.xs
lib/Variable/Magic.pm

index 7089937bddc2b8f61f199019b3e48be2aa8145d5..d9eab57a9589b31e160ffc517d3b58892c656e75 100644 (file)
--- a/Magic.xs
+++ b/Magic.xs
@@ -498,7 +498,8 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) {
 #define VMG_OP_INFO_NAME   1
 #define VMG_OP_INFO_OBJECT 2
 
-STATIC STRLEN *vmg_op_name_len = NULL;
+STATIC U32     vmg_op_name_refcnt = 0;
+STATIC STRLEN *vmg_op_name_len    = NULL;
 
 STATIC HV *vmg_b__op_stash = NULL;
 
@@ -512,6 +513,7 @@ STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo) {
     for (t = 0; t < OP_max; ++t)
      vmg_op_name_len[t] = strlen(PL_op_name[t]);
    }
+   ++vmg_op_name_refcnt;
    break;
   case VMG_OP_INFO_OBJECT:
    if (!vmg_b__op_stash) {
@@ -524,6 +526,22 @@ STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo) {
  }
 }
 
+STATIC void vmg_op_info_deinit(unsigned int opinfo) {
+ switch (opinfo) {
+  case VMG_OP_INFO_NAME:
+   if (vmg_op_name_refcnt > 0)
+    --vmg_op_name_refcnt;
+   if (!vmg_op_name_refcnt && vmg_op_name_len) {
+    Safefree(vmg_op_name_len);
+    vmg_op_name_len = NULL;
+   }
+   break;
+  case VMG_OP_INFO_OBJECT:
+  default:
+   break;
+ }
+}
+
 STATIC SV *vmg_op_info(pTHX_ unsigned int opinfo) {
 #define vmg_op_info(W) vmg_op_info(aTHX_ (W))
  if (!PL_op)
@@ -877,6 +895,9 @@ STATIC int vmg_wizard_free(pTHX_ SV *wiz, MAGIC *mg) {
  if (w->cb_delete != NULL) { SvREFCNT_dec(SvRV(w->cb_delete)); }
 #endif /* VMG_UVAR */
 
+ if (w->opinfo)
+  vmg_op_info_deinit(w->opinfo);
+
  Safefree(w->vtbl);
  Safefree(w);
 
@@ -1269,13 +1290,3 @@ CODE:
  RETVAL = newSVuv(vmg_dispell(SvRV(sv), sig));
 OUTPUT:
  RETVAL
-
-void
-_cleanup()
-PROTOTYPE:
-PPCODE:
- if (vmg_op_name_len) {
-  Safefree(vmg_op_name_len);
-  vmg_op_name_len = NULL;
- }
- XSRETURN(0);
index 00c86bae5c6b35d2076fd4c3eb04cc2dd2f2202b..4456efbaa6f11187b9903e7f6102cfac4cef569e 100644 (file)
@@ -479,8 +479,6 @@ our %EXPORT_TAGS    = (
 our @EXPORT_OK      = map { @$_ } values %EXPORT_TAGS;
 $EXPORT_TAGS{'all'} = [ @EXPORT_OK ];
 
-END { _cleanup() }
-
 =head1 CAVEATS
 
 If you store a magic object in the private data slot, the magic won't be accessible by L</getdata> since it's not copied by assignation.