summaryrefslogtreecommitdiff
path: root/gv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-10-27 11:24:52 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-10-28 16:15:09 -0700
commit0fbaa0e5e2fb0ff6f79a72915095a1325ebcd12e (patch)
treea9d20aee27a2ea44a3f54ef817f51df6d44ca430 /gv.c
parent0ca9877d08d37b8bc87c72cc832142c90f929378 (diff)
downloadperl-0fbaa0e5e2fb0ff6f79a72915095a1325ebcd12e.tar.gz
gv:gv_try_downgrade: Leave PL_stderrgv alone
gv_try_downgrade exists to remove globs and subs that were (possibly temporarily) vivified by bareword lookup. It is called whenever a gvop is freed and its gv looks like a candidate for downgrading. That means it applies, not only to potential sub calls, but also to *foo and *bar. gv_try_downgrade may delete a glob from the stash alto- gether if it is empty. So eval "*foo if 0" may delete the *foo glob. PL_stderrgv is a shortcut variable that points to *STDERR. When PL_stderrgv is null, the real stderr is used as a fallback. If gv_try_downgrade deletes *STDERR (which causes PL_stderrgv to be cleared), it can could the behaviour, which is not supposed to happen. It doesn’t actually delete *STDERR right now, because undef() vivifies the scalar slot, disqualifying the glob from downgrading. If we change undef not to vivify the scalar slot (I plan to soon, and this commit prepares for it), then this is what would happen without this commit: $ perl -le 'close *{"STDERR"}; undef *{"STDERR"}; eval "*STDERR if 0"; *{"STDERR"} = *STDOUT{IO}; warn' $ perl -le 'close *{"STDERR"}; undef *{"STDERR"}; *{"STDERR"} = *STDOUT{IO}; warn' Warning: something's wrong at -e line 1. Notice how the first one-liner (with the eval) produces no output.
Diffstat (limited to 'gv.c')
-rw-r--r--gv.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/gv.c b/gv.c
index 70e638efba..93e6ccc95b 100644
--- a/gv.c
+++ b/gv.c
@@ -3320,7 +3320,7 @@ Perl_gv_try_downgrade(pTHX_ GV *gv)
!GvSV(gv) && !GvAV(gv) && !GvHV(gv) && !GvIOp(gv) && !GvFORM(gv) &&
GvEGVx(gv) == gv && (stash = GvSTASH(gv))))
return;
- if (gv == PL_statgv) return;
+ if (gv == PL_statgv || gv == PL_stderrgv) return;
if (SvMAGICAL(gv)) {
MAGIC *mg;
/* only backref magic is allowed */