From 204263bc1eb63f1dfd6180c05dca8cec2c319504 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Sat, 24 Dec 2011 23:27:30 -0800 Subject: [PATCH] select() sometimes returns invalid string The return value from select() is sometimes a string, and sometimes a globref. It was originally always a string, but typeglobs not to be found under their names in their stashes started being returned as references in 5.002 beta 1 (4633a7c4b). The logic is a little faulty, though, as sometimes the name that is returned cannot be used to find the glob: $ perl -le ' open "foo::bar", ">/dev/ttys009"; select foo::bar; my $handle = \*foo::bar; my $stash = \%foo::bar; *foo:: = *bar::; print "hello"; select select; print "hello" or warn $! ' Bad file descriptor at -e line 9. In this example, /dev/ttys009 is another terminal window. "hello" only appears once, not twice. --- pp_sys.c | 5 ++++- t/op/select.t | 10 +++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pp_sys.c b/pp_sys.c index 78a51ae..661e0fc 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -1231,7 +1231,10 @@ PP(pp_select) if (! hv) XPUSHs(&PL_sv_undef); else { - GV * const * const gvp = (GV**)hv_fetch(hv, GvNAME(egv), HEK_UTF8(GvNAME_HEK(egv)) ? -GvNAMELEN(egv) : GvNAMELEN(egv), FALSE); + GV * const * const gvp = + HvENAME(hv) + ? (GV**)hv_fetch(hv, GvNAME(egv), HEK_UTF8(GvNAME_HEK(egv)) ? -GvNAMELEN(egv) : GvNAMELEN(egv), FALSE) + : NULL; if (gvp && *gvp == egv) { gv_efullname4(TARG, PL_defoutgv, NULL, TRUE); XPUSHTARG; diff --git a/t/op/select.t b/t/op/select.t index 7c27f6f..06caf1d 100644 --- a/t/op/select.t +++ b/t/op/select.t @@ -5,7 +5,7 @@ BEGIN { require './test.pl'; } -plan reverse 7; +plan reverse 8; open my $fh, "test.pl" or die "$0 unfortunately cannot open test.pl: $!"; @@ -17,3 +17,11 @@ is select, $fh, 'the ref returned references the right referent'; is select(STDOUT), $fh, 'select previous ref when setting to bareword'; is select, 'main::STDOUT', 'switching back to STDOUT'; is ref\select, 'SCALAR', 'and STDOUT is a plain string'; + +open foo::bar, "test.pl" or die "$0 sadly cannot open test.pl: $!"; +select foo::bar; +$handle = \*foo::bar; +$stash = \%foo::; +*foo:: = *bar::; +is select, $handle, + 'select returns ref for glob whose stash has been detached'; -- 2.7.4