# define SvREFCNT_inc_simple_void(sv) ((void) SvREFCNT_inc(sv))
#endif
+#ifndef SvREFCNT_dec_NN
+# define SvREFCNT_dec_NN(sv) ((void) SvREFCNT_dec(sv))
+#endif
+
#ifndef mPUSHu
# define mPUSHu(U) PUSHs(sv_2mortal(newSVuv(U)))
#endif
typedef struct {
SV *sv;
+ SV *rsv; /* The ref to the sv currently being freed, pushed on the stack */
int in_eval;
I32 base;
} vmg_svt_free_cleanup_ud;
SV *sv = ud->sv;
MAGIC *mg;
+ /* Silently undo the ref - don't trigger destruction in the referent
+ * for a second time */
+ if (SvROK(ud->rsv) && SvRV(ud->rsv) == sv) {
+ --SvREFCNT(sv);
+ SvRV_set(ud->rsv, NULL);
+ SvROK_off(ud->rsv);
+ }
+ SvREFCNT_dec_NN(ud->rsv);
+
/* We are about to croak() while sv is being destroyed. Try to clean up
* things a bit. */
mg = SvMAGIC(sv);
vmg_mg_del(sv, NULL, mg, mg->mg_moremagic);
mg_magical(sv);
}
- SvREFCNT_dec(sv);
+ SvREFCNT_dec(sv); /* Re-trigger destruction */
vmg_dispell_guard_oncroak(aTHX_ NULL);
PUSHMARK(SP);
EXTEND(SP, 2);
- PUSHs(sv_2mortal(newRV_inc(sv)));
+ /* This will bump the refcount of sv from 0 to 1 */
+ ud.rsv = newRV_inc(sv);
+ PUSHs(ud.rsv);
PUSHs(mg->mg_obj ? mg->mg_obj : &PL_sv_undef);
if (w->opinfo)
XPUSHs(vmg_op_info(w->opinfo));
POPSTACK;
+ /* Silently undo the ref - don't trigger destruction in the referent
+ * for a second time */
+ if (SvROK(ud.rsv) && SvRV(ud.rsv) == sv) {
+ SvRV_set(ud.rsv, NULL);
+ SvROK_off(ud.rsv);
+ --SvREFCNT(sv); /* silent */
+ }
+ SvREFCNT_dec_NN(ud.rsv);
+
FREETMPS;
LEAVE;