summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChip Salzenberg <chip@atlantic.net>1996-12-19 16:11:07 +1200
committerChip Salzenberg <chip@atlantic.net>1996-12-20 11:14:00 +1200
commit477f5d66753fb2a661264a381aecf12e9a9beac1 (patch)
tree88a794a797f0a2ce677f645064f436f8e41b5da3
parent178c63054ce0b6f5d9bd91ada1261d807e487123 (diff)
downloadperl-477f5d66753fb2a661264a381aecf12e9a9beac1.tar.gz
Allow DESTROY to make refs to dying objects
-rw-r--r--sv.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/sv.c b/sv.c
index 95c3340e94..3784350e3e 100644
--- a/sv.c
+++ b/sv.c
@@ -330,13 +330,17 @@ SV* sv;
}
#endif
+static bool in_clean_objs = FALSE;
+
void
sv_clean_objs()
{
+ in_clean_objs = TRUE;
#ifndef DISABLE_DESTRUCTOR_KLUDGE
visit(do_clean_named_objs);
#endif
visit(do_clean_objs);
+ in_clean_objs = FALSE;
}
static void
@@ -348,14 +352,14 @@ SV* sv;
SvREFCNT_dec(sv);
}
-static int in_clean_all = 0;
+static bool in_clean_all = FALSE;
void
sv_clean_all()
{
- in_clean_all = 1;
+ in_clean_all = TRUE;
visit(do_clean_all);
- in_clean_all = 0;
+ in_clean_all = FALSE;
}
void
@@ -2560,6 +2564,7 @@ register SV *nsv;
}
SvREFCNT(sv) = 0;
sv_clear(sv);
+ assert(!SvREFCNT(sv));
StructCopy(nsv,sv,SV);
SvREFCNT(sv) = refcnt;
SvFLAGS(nsv) |= SVTYPEMASK; /* Mark as freed */
@@ -2608,7 +2613,7 @@ register SV *sv;
--sv_objcount; /* XXX Might want something more general */
}
if (SvREFCNT(sv)) {
- SV *ret;
+ SV *ret;
if ( perldb
&& (ret = perl_get_sv("DB::ret", FALSE))
&& SvROK(ret) && SvRV(ret) == sv && SvREFCNT(sv) == 1) {
@@ -2616,8 +2621,12 @@ register SV *sv;
SvRV(ret) = 0;
SvROK_off(ret);
SvREFCNT(sv) = 0;
- } else {
- croak("DESTROY created new reference to dead object");
+ }
+ else {
+ if (in_clean_objs)
+ croak("DESTROY created new reference to dead object");
+ /* DESTROY gave object new lease on life */
+ return;
}
}
}
@@ -2760,7 +2769,8 @@ SV *sv;
}
#endif
sv_clear(sv);
- del_SV(sv);
+ if (! SvREFCNT(sv))
+ del_SV(sv);
}
STRLEN