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

localizing $? loses exit status from die() #7366

Open
p5pRT opened this issue Jun 15, 2004 · 7 comments
Open

localizing $? loses exit status from die() #7366

p5pRT opened this issue Jun 15, 2004 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 15, 2004

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

Searchable as RT30296$

@p5pRT
Copy link
Author

p5pRT commented Jun 15, 2004

From cjwatson@debian.org

Created by cjwatson@debian.org

  $ perl -e 'die "hello";'; echo $?
  hello at -e line 1.
  255

  $ perl -e 'local $?; die "hello";'; echo $?
  hello at -e line 1.
  0

die() is specified in perlfunc as follows​:

  Outside an "eval", prints the value of LIST to "STDERR" and exits with
  the current value of $! (errno). If $! is 0, exits with the value of
  "($? >> 8)" (backtick `command` status). If "($? >> 8)" is 0, exits
  with 255.

... and $? is specified in perlvar as follows​:

  Inside an "END" subroutine $? contains the value that is going to be
  given to "exit()". You can modify $? in an "END" subroutine to change
  the exit status of your program.

However, the localization above is not within an END block, and I don't
see anything else in the documentation to suggest that the unwinding of
the save stack should clobber the exit status from die().

It seems useful to be able to localize $? in order to write subs that
affect their callers' state as little as possible, so this behaviour
seems unfortunate​: perhaps die() could stash the exit status somewhere
other than $? until END blocks are called.

If the current behaviour is really desired, then it would be nice to
have it documented in L<perlfunc/die> and L<perlvar/$?>.

(Ian Jackson discovered this; I'm just passing it on.)

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl v5.8.4:

Configured by Debian Project at Wed May 12 00:26:52 EST 2004.

Summary of my perl5 (revision 5 version 8 subversion 4) configuration:
  Platform:
    osname=linux, osvers=2.4.26, archname=powerpc-linux-thread-multi
    uname='linux vir 2.4.26 #1 thu apr 15 23:31:26 est 2004 ppc gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=powerpc-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.4 -Dsitearch=/usr/local/lib/perl/5.8.4 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.4 -Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O1',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include'
    ccversion='', gccversion='3.3.3 (Debian 20040429)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=8
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so.5.8.4
    gnulibc_version='2.3.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.4:
    /etc/perl
    /usr/local/lib/perl/5.8.4
    /usr/local/share/perl/5.8.4
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.8
    /usr/share/perl/5.8
    /usr/local/lib/site_perl
    .


Environment for perl v5.8.4:
    HOME=/home/cjwatson
    LANG (unset)
    LANGUAGE (unset)
    LC_COLLATE=C
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/cjwatson/bin:/usr/lib/surfraw:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/usr/sbin:/sbin
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Apr 23, 2005

From @smpeters

[cjwatson@​debian.org - Tue Jun 15 16​:19​:35 2004]​:

This is a bug report for perl from cjwatson@​debian.org,
generated with the help of perlbug 1.35 running under perl v5.8.4.

-----------------------------------------------------------------
[Please enter your report here]

$ perl -e 'die "hello";'; echo $?
hello at -e line 1.
255

$ perl -e 'local $?; die "hello";'; echo $?
hello at -e line 1.
0

die() is specified in perlfunc as follows​:

Outside an "eval", prints the value of LIST to "STDERR" and exits
with
the current value of $! (errno). If $! is 0, exits with the value
of
"($? &gt;&gt; 8)" (backtick `command` status). If "($? >> 8)" is 0, exits
with 255.

... and $? is specified in perlvar as follows​:

Inside an "END" subroutine $? contains the value that is going to be
given to "exit()". You can modify $? in an "END" subroutine to
change
the exit status of your program.

However, the localization above is not within an END block, and I
don't
see anything else in the documentation to suggest that the unwinding
of
the save stack should clobber the exit status from die().

It seems useful to be able to localize $? in order to write subs that
affect their callers' state as little as possible, so this behaviour
seems unfortunate​: perhaps die() could stash the exit status somewhere
other than $? until END blocks are called.

If the current behaviour is really desired, then it would be nice to
have it documented in L<perlfunc/die> and L<perlvar/$?>.

(Ian Jackson discovered this; I'm just passing it on.)

Actually, local isn't the only cause. Certain modules seem to help this
out.

perl -e '$?=0; die "hello";' ; echo $?
hello at -e line 1.
255
perl -MO=Deparse -e '$?=0; die "hello";' ; echo $?
$? = 0;
die 'hello';
-e syntax OK
0

@p5pRT
Copy link
Author

p5pRT commented Apr 23, 2005

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

@p5pRT
Copy link
Author

p5pRT commented Apr 23, 2005

From @iabyn

On Sat, Apr 23, 2005 at 02​:17​:52PM -0000, Steve Peters via RT wrote​:

Actually, local isn't the only cause. Certain modules seem to help this
out.

perl -e '$?=0; die "hello";' ; echo $?
hello at -e line 1.
255
perl -MO=Deparse -e '$?=0; die "hello";' ; echo $?
$? = 0;
die 'hello';
-e syntax OK
0

Er no; with Deparse, the code is never executed, so the die never happens.

--
Spock (or Data) is fired from his high-ranking position for not being able
to understand the most basic nuances of about one in three sentences that
anyone says to him.
  -- Things That Never Happen in "Star Trek" #19

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2012

From @Hugmeir

On Tue Jun 15 16​:19​:35 2004, cjwatson@​debian.org wrote​:

This is a bug report for perl from cjwatson@​debian.org,
generated with the help of perlbug 1.35 running under perl v5.8.4.

-----------------------------------------------------------------
[Please enter your report here]

$ perl -e 'die "hello";'; echo $?
hello at -e line 1.
255

$ perl -e 'local $?; die "hello";'; echo $?
hello at -e line 1.
0

die() is specified in perlfunc as follows​:

Outside an "eval", prints the value of LIST to "STDERR" and exits
with
the current value of $! (errno). If $! is 0, exits with the value
of
"($? &gt;&gt; 8)" (backtick `command` status). If "($? >> 8)" is 0, exits
with 255.

... and $? is specified in perlvar as follows​:

Inside an "END" subroutine $? contains the value that is going to be
given to "exit()". You can modify $? in an "END" subroutine to
change
the exit status of your program.

However, the localization above is not within an END block, and I
don't
see anything else in the documentation to suggest that the unwinding
of
the save stack should clobber the exit status from die().

It seems useful to be able to localize $? in order to write subs that
affect their callers' state as little as possible, so this behaviour
seems unfortunate​: perhaps die() could stash the exit status somewhere
other than $? until END blocks are called.

If the current behaviour is really desired, then it would be nice to
have it documented in L<perlfunc/die> and L<perlvar/$?>.

(Ian Jackson discovered this; I'm just passing it on.)

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags​:
category=core
severity=low
---
Site configuration information for perl v5.8.4​:

Configured by Debian Project at Wed May 12 00​:26​:52 EST 2004.

Summary of my perl5 (revision 5 version 8 subversion 4) configuration​:
Platform​:
osname=linux, osvers=2.4.26, archname=powerpc-linux-thread-multi
uname='linux vir 2.4.26 #1 thu apr 15 23​:31​:26 est 2004 ppc
gnulinux '
config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN
-Dcccdlflags=-fPIC -Darchname=powerpc-linux -Dprefix=/usr
-Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8
-Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5
-Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local
-Dsitelib=/usr/local/share/perl/5.8.4
-Dsitearch=/usr/local/lib/perl/5.8.4 -Dman1dir=/usr/share/man/man1
-Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1
-Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl
-Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm
-Duseshrplib -Dlibperl=libperl.so.5.8.4 -Dd_dosuid -des'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler​:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS
-DDEBIAN -fno-strict-aliasing -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O1',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN
-fno-strict-aliasing -I/usr/local/include'
ccversion='', gccversion='3.3.3 (Debian 20040429)',
gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=8
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries​:
ld='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
perllibs=-ldl -lm -lpthread -lc -lcrypt
libc=/lib/libc-2.3.2.so, so=so, useshrplib=true,
libperl=libperl.so.5.8.4
gnulibc_version='2.3.2'
Dynamic Linking​:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches​:

---
@​INC for perl v5.8.4​:
/etc/perl
/usr/local/lib/perl/5.8.4
/usr/local/share/perl/5.8.4
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.8
/usr/share/perl/5.8
/usr/local/lib/site_perl
.

---
Environment for perl v5.8.4​:
HOME=/home/cjwatson
LANG (unset)
LANGUAGE (unset)
LC_COLLATE=C
LD_LIBRARY_PATH (unset)
LOGDIR (unset)

PATH=/home/cjwatson/bin​:/usr/lib/surfraw​:/usr/local/bin​:/usr/bin​:/bin​:/usr/bin/X11​:/usr/games​:/usr/sbin​:/sbin

PERL\_BADLANG \(unset\)
SHELL=/bin/bash

This is still present in 5.14.2 and blead. But, personally, I consider
this not-a-bug, or maybe a wishlist item​: local is doing what it should
do, localizing a variable for the duration of the current scope. Since
this is script-scoped, it's not terribly unexpected that once the script
ends the variables regain their original values.

I think these two snippets show that local() is working as expected​:
$ perl -e '$? = 3; local $?; die "hello";'; echo $?

$ perl -e 'local $?; CORE​::dump;'; echo $?

@p5pRT
Copy link
Author

p5pRT commented May 3, 2012

From @nwc10

On Mon, Apr 30, 2012 at 01​:01​:13AM -0700, Brian Fraser via RT wrote​:

On Tue Jun 15 16​:19​:35 2004, cjwatson@​debian.org wrote​:

$ perl -e 'die "hello";'; echo $?
hello at -e line 1.
255

$ perl -e 'local $?; die "hello";'; echo $?
hello at -e line 1.
0

die() is specified in perlfunc as follows​:

Outside an "eval", prints the value of LIST to "STDERR" and exits
with
the current value of $! (errno). If $! is 0, exits with the value
of
"($? &gt;&gt; 8)" (backtick `command` status). If "($? >> 8)" is 0, exits
with 255.

... and $? is specified in perlvar as follows​:

Inside an "END" subroutine $? contains the value that is going to be
given to "exit()". You can modify $? in an "END" subroutine to
change
the exit status of your program.

However, the localization above is not within an END block, and I
don't
see anything else in the documentation to suggest that the unwinding
of
the save stack should clobber the exit status from die().

It seems useful to be able to localize $? in order to write subs that
affect their callers' state as little as possible, so this behaviour
seems unfortunate​: perhaps die() could stash the exit status somewhere
other than $? until END blocks are called.

If the current behaviour is really desired, then it would be nice to
have it documented in L<perlfunc/die> and L<perlvar/$?>.

(Ian Jackson discovered this; I'm just passing it on.)

This is still present in 5.14.2 and blead. But, personally, I consider
this not-a-bug, or maybe a wishlist item​: local is doing what it should
do, localizing a variable for the duration of the current scope. Since
this is script-scoped, it's not terribly unexpected that once the script
ends the variables regain their original values.

I think these two snippets show that local() is working as expected​:
$ perl -e '$? = 3; local $?; die "hello";'; echo $?

$ perl -e 'local $?; CORE​::dump;'; echo $?

The bug is in die, not in local. local is working fine, die is not. die is
documented as exiting non-zero. There's no exception made for "unless $? is
localised". There shouldn't be any exceptions made for code outside END
blocks.

The fact that local is a dynamic scope results in the potential for messy
action at a distance bugs. The subroutine elsewhere() in my example is
intended to throw an exception if it fails. Uncaught exceptions should cause
perl to exit non-zero. Yet​:

$ perl -e 'sub elsewhere {use autodie; open my $fh, "/foo"} elsewhere()'
Can't open($fh, '/foo')​: No such file or directory at -e line 1
$ echo $?
255

whereas if I localise $?

$ perl -e 'sub elsewhere {use autodie; open my $fh, "/foo"} local $?; elsewhere()'
Can't open($fh, '/foo')​: No such file or directory at -e line 1
$ echo $?
0

the exit code is zero, which is wrong.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 3, 2012

From @ikegami

On Mon, Apr 30, 2012 at 4​:01 AM, Brian Fraser via RT <
perlbug-followup@​perl.org> wrote​:

On Tue Jun 15 16​:19​:35 2004, cjwatson@​debian.org wrote​:
This is still present in 5.14.2 and blead. But, personally, I consider
this not-a-bug, or maybe a wishlist item​: local is doing what it should
do, localizing a variable for the duration of the current scope.

die() is within scope of the local $?, so it should see the local $?, but
it doesn't. It sees the $? that's not even in scope. That's a bug.

perl -E"$?=3; local $?=4; die;"
Died at -e line 1.

echo %ERRORLEVEL%
3

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

2 participants