summaryrefslogtreecommitdiff
path: root/gv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-09-21 07:43:12 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-09-21 07:44:06 -0700
commitc947bc1dc2208798835a2ed509163cd71f20b218 (patch)
tree2ef445454c346ca20aa781fc139e896085187394 /gv.c
parent66ea08c616b11ff6bfed72f897895a6e21664769 (diff)
downloadperl-c947bc1dc2208798835a2ed509163cd71f20b218.tar.gz
Remove bad assertion in gv.c:newGP
See the thread starting at <20130805090753.12203.qmail@lists-nntp.develooper.com>. Under the assumption that PL_curcop could never be null in newGP (even when set to null by S_cop_free in op.c), I added an assertion to newGP, which still leaving the null checks in place. The idea was that, if PL_curcop is ever null there, we want to know about it, since it is probably a bug. It turns out this code (reduced from DBIx::Class’s test suite), can fail that assertion: INIT { bless {} and exit; } exit() calls leave_scope, which frees the INIT block. Since PL_curcop (the statement inside INIT) would end up pointing to free memory, it is set to null. When it exits, call_sv does FREETMPS: case 2: /* my_exit() was called */ SET_CURSTASH(PL_defstash); FREETMPS; JMPENV_POP; my_exit_jump(); assert(0); /* NOTREACHED */ FREETMPS ends up freeing the object (bless {}), which results in a DESTROY method lookup. For the sake of caching methods, *main::DESTROY is autovivified. GV creation trips on the assertion in newGP that makes sure PL_curcop is null. So this proves that we really do need to check for a null PL_curcop in newGP. While we could avoid having DESTROY lookup vivify *main::DESTROY (since the cache there would only be used for explicit ->DESTROY calls, the usual DESTROY cache being stuffed into SvSTASH(stash)), that would complicate things for no gain.
Diffstat (limited to 'gv.c')
-rw-r--r--gv.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/gv.c b/gv.c
index fc4393eb78..9f0b57e6a5 100644
--- a/gv.c
+++ b/gv.c
@@ -176,9 +176,10 @@ Perl_newGP(pTHX_ GV *const gv)
gp->gp_sv = newSV(0);
#endif
- /* PL_curcop should never be null here. */
- assert(PL_curcop);
- /* But for non-debugging builds play it safe */
+ /* PL_curcop may be null here. E.g.,
+ INIT { bless {} and exit }
+ frees INIT before looking up DESTROY (and creating *DESTROY)
+ */
if (PL_curcop) {
gp->gp_line = CopLINE(PL_curcop); /* 0 otherwise Newxz */
#ifdef USE_ITHREADS