summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-08-17 23:58:47 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-08-17 23:58:47 -0700
commitc716b3beb77406159d18fd52251821fee641f9fc (patch)
treeb3304d82ae5b06d3fb56209a905aaf1554e33599 /sv.c
parentbe9260535f65befe9615312821574755a8d04344 (diff)
downloadperl-c716b3beb77406159d18fd52251821fee641f9fc.tar.gz
[perl #114864] Make UNIVERSAL::DESTROY changes invalidate caches
Commit 8c34e50d inadvertently caused DESTROY caches not to be reset when UNIVERSAL::DESTROY changes. Normally, a change to a method will cause mro_method_changed_in to be called on all subclasses, but mro.c cheats for UNIVERSAL and just does ++PL_sub_generation. So clearing the DESTROY cache explicitly in mro_method_changed_in is clearly not enough.
Diffstat (limited to 'sv.c')
-rw-r--r--sv.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/sv.c b/sv.c
index 044dc9db90..7737eedcd6 100644
--- a/sv.c
+++ b/sv.c
@@ -6565,14 +6565,21 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
assert(SvTYPE(stash) == SVt_PVHV);
if (HvNAME(stash)) {
CV* destructor = NULL;
+ assert (SvOOK(stash));
if (!SvOBJECT(stash)) destructor = (CV *)SvSTASH(stash);
- if (!destructor) {
+ if (!destructor || HvMROMETA(stash)->destroy_gen
+ != PL_sub_generation)
+ {
GV * const gv =
gv_fetchmeth_autoload(stash, "DESTROY", 7, 0);
if (gv) destructor = GvCV(gv);
if (!SvOBJECT(stash))
+ {
SvSTASH(stash) =
destructor ? (HV *)destructor : ((HV *)0)+1;
+ HvAUX(stash)->xhv_mro_meta->destroy_gen =
+ PL_sub_generation;
+ }
}
assert(!destructor || destructor == ((CV *)0)+1
|| SvTYPE(destructor) == SVt_PVCV);