Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

goto LABEL doesn't work from within $SIG{__DIE__} #8987

Open
p5pRT opened this issue Aug 3, 2007 · 14 comments
Open

goto LABEL doesn't work from within $SIG{__DIE__} #8987

p5pRT opened this issue Aug 3, 2007 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 3, 2007

Migrated from rt.perl.org#44367 (status was 'open')

Searchable as RT44367$

@p5pRT
Copy link
Author

p5pRT commented Aug 3, 2007

From @steve-m-hay

Created by SteveHay@planit.com

This is a bug report for perl from SteveHay@​planit.com,
generated with the help of perlbug 1.35 running under perl v5.8.8.

-----------------------------------------------------------------
Should it be possible to goto LABEL from within a $SIG{__DIE__} ?

The man pages seem to suggest that it should​:

perlvar​:
When a __DIE__ hook routine returns, the exception processing continues
as it would have in the absence of the hook, unless the hook routine
itself exits via a goto, a loop exit, or a die().

perlsyn​:
The goto-LABEL form [...] can be used to go almost anywhere else within
the dynamic scope, including out of subroutines

However, it doesn't seem to work​:

print "one\n";
$SIG{__DIE__} = sub { goto three };
die "Dead!\n";
print "two\n";
three​:
print "three\n";

prints​:

one
Can't find label three at C​:\Temp\test.pl line 2.

I get the same result with perl-5.8.8 and perl-5.9.5.

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl v5.8.8:

Configured by shay at Wed Aug  1 09:24:48 2007.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
  Platform:
    osname=MSWin32, osvers=5.1, archname=MSWin32-x86-multi-thread
    uname=''
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=undef
    usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=y, bincompat5005=undef
  Compiler:
    cc='cl', ccflags ='-nologo -Gf -W3 -MD -Zi -DNDEBUG -O1 -DWIN32
-D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT  -DPERL_DEBUGGING_MSTATS
-DPERL_IMPLICIT_CONTEXT -DUSE_PERLIO -DPERL_MSVCRT_READFIX',
    optimize='-MD -Zi -DNDEBUG -O1',
    cppflags='-DWIN32'
    ccversion='12.00.8804', gccversion='', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=10
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='link', ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf
-libpath:"C:\perl5\lib\CORE"  -machine:x86'
    libpth="C:\Program Files\Microsoft Visual Studio\VC98\lib"
    libs=  oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib
netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib
odbc32.lib odbccp32.lib msvcrt.lib
    perllibs=  oldnames.lib kernel32.lib user32.lib gdi32.lib
winspool.lib  comdlg32.lib advapi32.lib shell32.lib ole32.lib
oleaut32.lib  netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib
version.lib odbc32.lib odbccp32.lib msvcrt.lib
    libc=msvcrt.lib, so=dll, useshrplib=yes, libperl=perl58.lib
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug
-opt:ref,icf  -libpath:"C:\perl5\lib\CORE"  -machine:x86'

Locally applied patches:
    


@INC for perl v5.8.8:
    C:/perl5/lib
    C:/perl5/site/lib
    .


Environment for perl v5.8.8:
    HOME (unset)
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
 
PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\perl5\bi
n
    PERL_BADLANG (unset)
    SHELL (unset)

@p5pRT
Copy link
Author

p5pRT commented Jan 3, 2012

From @jkeenan

On Fri Aug 03 06​:30​:49 2007, Steve.Hay@​uk.radan.com wrote​:

-----------------------------------------------------------------
Should it be possible to goto LABEL from within a $SIG{__DIE__} ?

The man pages seem to suggest that it should​:

perlvar​:
When a __DIE__ hook routine returns, the exception processing continues
as it would have in the absence of the hook, unless the hook routine
itself exits via a goto, a loop exit, or a die().

perlsyn​:
The goto-LABEL form [...] can be used to go almost anywhere else within
the dynamic scope, including out of subroutines

However, it doesn't seem to work​:

print "one\n";
$SIG{__DIE__} = sub { goto three };
die "Dead!\n";
print "two\n";
three​:
print "three\n";

prints​:

one
Can't find label three at C​:\Temp\test.pl line 2.

I confirmed the above case using Perl 5.14.2 on Darwin/PPC. But then I
wondered, "What if I used a name subroutine rather than a coderef?"

#####
$ cat 44367.pl
#!/usr/local/bin/perl
use strict;
use warnings;

print "one\n";
$SIG{__DIE__} = three();
die "Dead!\n";
print "two\n";
THREE​:
print "three\n";

sub three { goto THREE };
#####

Output​:

#####
$ perl 44367.pl
one
three
#####

Thoughts?

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Jan 3, 2012

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 3, 2012

From @cpansprout

On Mon Jan 02 17​:52​:29 2012, jkeenan wrote​:

On Fri Aug 03 06​:30​:49 2007, Steve.Hay@​uk.radan.com wrote​:

-----------------------------------------------------------------
Should it be possible to goto LABEL from within a $SIG{__DIE__} ?

The man pages seem to suggest that it should​:

perlvar​:
When a __DIE__ hook routine returns, the exception processing continues
as it would have in the absence of the hook, unless the hook routine
itself exits via a goto, a loop exit, or a die().

perlsyn​:
The goto-LABEL form [...] can be used to go almost anywhere else within
the dynamic scope, including out of subroutines

However, it doesn't seem to work​:

print "one\n";
$SIG{__DIE__} = sub { goto three };
die "Dead!\n";
print "two\n";
three​:
print "three\n";

prints​:

one
Can't find label three at C​:\Temp\test.pl line 2.

I confirmed the above case using Perl 5.14.2 on Darwin/PPC. But then I
wondered, "What if I used a name subroutine rather than a coderef?"

#####
$ cat 44367.pl
#!/usr/local/bin/perl
use strict;
use warnings;

print "one\n";
$SIG{__DIE__} = three();
die "Dead!\n";
print "two\n";
THREE​:
print "three\n";

sub three { goto THREE };
#####

Output​:

#####
$ perl 44367.pl
one
three
#####

Thoughts?

You just tried to assign the return value of three() to $SIG{__DIE__}.

This variation​:

#!/usr/local/bin/perl
use strict;
use warnings;

print "one\n";
$SIG{__DIE__} = 'three';
die "Dead!\n";
print "two\n";
THREE​:
print "three\n";

sub three { goto THREE };
__END__

prints this​:

one
Can't find label THREE at - line 12.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 4, 2012

From @iabyn

On Fri, Aug 03, 2007 at 06​:30​:50AM -0700, Steve Hay wrote​:

Should it be possible to goto LABEL from within a $SIG{__DIE__} ?

The man pages seem to suggest that it should​:

perlvar​:
When a __DIE__ hook routine returns, the exception processing continues
as it would have in the absence of the hook, unless the hook routine
itself exits via a goto, a loop exit, or a die().

perlsyn​:
The goto-LABEL form [...] can be used to go almost anywhere else within
the dynamic scope, including out of subroutines

However, it doesn't seem to work​:

print "one\n";
$SIG{__DIE__} = sub { goto three };
die "Dead!\n";
print "two\n";
three​:
print "three\n";

prints​:

one
Can't find label three at C​:\Temp\test.pl line 2.

I don't think it should be able to. I think the "via a goto" in the docs
meant 'goto &sub' rather than 'goto LABEL', and should be updated to
clarify this.

The reason I think this shouldn't work, is that SIG{__DIE__}, like
tied methods, may get called from anywhere, not just from within a perl
runloop​: i.e they can be triggered from within arbitrary C code.
So the only valid non-return sub exiting methods are those which trigger a
longjmp and unwind the C stack (i.e. exit and die). Of course 'goto &sub'
isn't really exiting, its just replacing the current sub with a new one,
and placing the same burden onto that.

--
The Enterprise is involved in a bizarre time-warp experience which is in
some way unconnected with the Late 20th Century.
  -- Things That Never Happen in "Star Trek" #14

@p5pRT
Copy link
Author

p5pRT commented Jan 8, 2012

From @iabyn

On Wed, Jan 04, 2012 at 12​:28​:56PM +0000, Dave Mitchell wrote​:

On Fri, Aug 03, 2007 at 06​:30​:50AM -0700, Steve Hay wrote​:

Should it be possible to goto LABEL from within a $SIG{__DIE__} ?

The man pages seem to suggest that it should​:

perlvar​:
When a __DIE__ hook routine returns, the exception processing continues
as it would have in the absence of the hook, unless the hook routine
itself exits via a goto, a loop exit, or a die().

perlsyn​:
The goto-LABEL form [...] can be used to go almost anywhere else within
the dynamic scope, including out of subroutines

However, it doesn't seem to work​:

print "one\n";
$SIG{__DIE__} = sub { goto three };
die "Dead!\n";
print "two\n";
three​:
print "three\n";

prints​:

one
Can't find label three at C​:\Temp\test.pl line 2.

I don't think it should be able to. I think the "via a goto" in the docs
meant 'goto &sub' rather than 'goto LABEL', and should be updated to
clarify this.

Docs now updated with

commit c94b42e
Author​: David Mitchell <davem@​iabyn.com>
AuthorDate​: Sun Jan 8 15​:45​:39 2012 +0000
Commit​: David Mitchell <davem@​iabyn.com>
CommitDate​: Sun Jan 8 15​:45​:39 2012 +0000

  clarify how $SIG{__DIE__} can return
 
  It can return via 'goto &sub', but not via 'goto LABEL'.
  The docs originally just said 'via goto'
 
  See [perl #44367].

M pod/perlvar.pod

--
The Enterprise is involved in a bizarre time-warp experience which is in
some way unconnected with the Late 20th Century.
  -- Things That Never Happen in "Star Trek" #14

@p5pRT
Copy link
Author

p5pRT commented Jan 8, 2012

From @cpansprout

On Wed Jan 04 04​:29​:41 2012, davem wrote​:

On Fri, Aug 03, 2007 at 06​:30​:50AM -0700, Steve Hay wrote​:

Should it be possible to goto LABEL from within a $SIG{__DIE__} ?

The man pages seem to suggest that it should​:

perlvar​:
When a __DIE__ hook routine returns, the exception processing continues
as it would have in the absence of the hook, unless the hook routine
itself exits via a goto, a loop exit, or a die().

perlsyn​:
The goto-LABEL form [...] can be used to go almost anywhere else within
the dynamic scope, including out of subroutines

However, it doesn't seem to work​:

print "one\n";
$SIG{__DIE__} = sub { goto three };
die "Dead!\n";
print "two\n";
three​:
print "three\n";

prints​:

one
Can't find label three at C​:\Temp\test.pl line 2.

I don't think it should be able to. I think the "via a goto" in the docs
meant 'goto &sub' rather than 'goto LABEL', and should be updated to
clarify this.

The reason I think this shouldn't work, is that SIG{__DIE__}, like
tied methods, may get called from anywhere, not just from within a perl
runloop​: i.e they can be triggered from within arbitrary C code.
So the only valid non-return sub exiting methods are those which trigger a
longjmp and unwind the C stack (i.e. exit and die). Of course 'goto &sub'
isn't really exiting, its just replacing the current sub with a new one,
and placing the same burden onto that.

Couldn’t goto-LABEL and loop controls be made to do a longjmp if the
target is on a different stack?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 8, 2012

From @iabyn

On Sun, Jan 08, 2012 at 11​:02​:58AM -0800, Father Chrysostomos via RT wrote​:

The reason I think this shouldn't work, is that SIG{__DIE__}, like
tied methods, may get called from anywhere, not just from within a perl
runloop​: i.e they can be triggered from within arbitrary C code.
So the only valid non-return sub exiting methods are those which trigger a
longjmp and unwind the C stack (i.e. exit and die). Of course 'goto &sub'
isn't really exiting, its just replacing the current sub with a new one,
and placing the same burden onto that.

Couldn’t goto-LABEL and loop controls be made to do a longjmp if the
target is on a different stack?

Not really. There's not a 1-1 correspondence between depth of nesting of
stacks and depth of JMPENV_PUSH. For example tied magic does a PUSHSTACK
but not a JMPENV_PUSH.

--
print+qq&$}$"$/$s$,$a$d$g$s$@​$.$q$,$​:$.$q$^$,$@​$a$$;$.$q$m&if+map{m,^\d{0\,},,${$​::{$'}}=chr($"+=$&amp;||1)}q&10m22,42}6​:17a22.3@​3;^2dg3q/s"&=~m*\d\*.*g

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2012

From @doy

So have we decided this is a wontfix then?

-doy

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2012

From @cpansprout

On Tue Jul 03 13​:17​:46 2012, doy wrote​:

So have we decided this is a wontfix then?

I haven’t. :-)

I still think it a wart from the point of view of the Perl language
(rather than the implementation) that goto works to exit subroutines and
evals, but not sort blocks, tie/overload methods, eval 'BEGIN {...}', etc.

I would still like to fix this.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 13, 2012

From @tsee

On 07/03/2012 10​:27 PM, Father Chrysostomos via RT wrote​:

On Tue Jul 03 13​:17​:46 2012, doy wrote​:

So have we decided this is a wontfix then?

I haven’t. :-)

I still think it a wart from the point of view of the Perl language
(rather than the implementation) that goto works to exit subroutines and
evals, but not sort blocks, tie/overload methods, eval 'BEGIN {...}', etc.

I would still like to fix this.

I won't stop you, but *please* don't fix this at the cost of
performance. My gut feeling is that this is because of some obscure
optimization such as "sort blocks do multicall" that makes a very big
difference in practice.

--Steffen

@p5pRT
Copy link
Author

p5pRT commented Aug 13, 2012

From @cpansprout

On Mon Aug 13 02​:03​:27 2012, smueller@​cpan.org wrote​:

On 07/03/2012 10​:27 PM, Father Chrysostomos via RT wrote​:

On Tue Jul 03 13​:17​:46 2012, doy wrote​:

So have we decided this is a wontfix then?

I haven’t. :-)

I still think it a wart from the point of view of the Perl language
(rather than the implementation) that goto works to exit subroutines and
evals, but not sort blocks, tie/overload methods, eval 'BEGIN
{...}', etc.

I would still like to fix this.

I won't stop you, but *please* don't fix this at the cost of
performance. My gut feeling is that this is because of some obscure
optimization such as "sort blocks do multicall" that makes a very big
difference in practice.

The reason it cannot exit a sort block is that sort is a single op that
starts a new runloop each time it calls the block (as opposed to map and
s/// which consist of multiple ops and use the main runloop).

The only overhead would be an extra setjmp for each runloop, which I
think would be negligible enough not to be reliably measurable.

--

Father Chrysostomos

@toddr
Copy link
Member

toddr commented Feb 13, 2020

@cpansprout do you still want to fix goto in this way?

@oodler577
Copy link

Hi, thanks to @xenu for pointing me to this issue. I ran into it while experimenting with a goto LABEL inside of an ALRM handler, here's there reproducer:

use strict;
use warnings;

local $SIG{ALRM} = sub {
  print qq{Alarm!! .. reArming ..\n};
  goto RETRY;
};

RETRY:
alarm 1;
print qq{Trying something that might timeout ...\n};
sleep 3;
alarm 0;

I was experimenting with retry mechanism for Try::ALRM (new) when I ran into this. I think fixing this would provide an advantage for what I am doing; but there are other ways to go about it. It'd still be cool to see working. TY!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants