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

pads being reused in coderefs called from DESTROY #13170

Closed
p5pRT opened this issue Aug 15, 2013 · 17 comments
Closed

pads being reused in coderefs called from DESTROY #13170

p5pRT opened this issue Aug 15, 2013 · 17 comments

Comments

@p5pRT
Copy link

@p5pRT p5pRT commented Aug 15, 2013

Migrated from rt.perl.org#119311 (status was 'resolved')

Searchable as RT119311$

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 15, 2013

From @doy

Created by @doy

Given this script​:

  sub foo {
  my ($block, $other) = @​_;

  my $got;
  die "this is clearly a bug" if $got;

  $got = $other;

  $block->();
  }

  {
  package Foo;

  sub DESTROY {
  :​:foo(sub { }, 1);
  return;
  }
  }

  # "exit(0) unless fork" also triggers the bug,
  # but a bare "fork" doesn't
  foo(sub { my $o = bless {}, 'Foo'; exit(0) if fork }, 1);

$got is keeping its previous value when foo() is called from the DESTROY
method. This has been broken since 5.8.0, a bisect points to 840a7b7 as
where the bug was introduced​:

  commit 840a7b7
  Author​: Ilya Zakharevich <ilya@​math.berkeley.edu>
  Date​: Mon Dec 4 19​:40​:25 2000 -0500

  Re​: [PATCH] The largest hoax of all times?
  Date​: Tue, 5 Dec 2000 00​:40​:25 -0500
  Message-ID​: <20001205004025.A4050@​monk.mps.ohio-state.edu>

  Subject​: Re​: [PATCH] The largest hoax of all times?
  From​: Ilya Zakharevich <ilya@​math.ohio-state.edu>
  Date​: Mon, 4 Dec 2000 23​:55​:53 -0500
  Message-ID​: <20001204235553.A1140@​monk.mps.ohio-state.edu>

  Subject​: Re​: [PATCH] The largest hoax of all times?
  From​: Ilya Zakharevich <ilya@​math.ohio-state.edu>
  Date​: Tue, 5 Dec 2000 01​:28​:45 -0500
  Message-ID​: <20001205012844.A4227@​monk.mps.ohio-state.edu>

  Fix the unpredictable order of DESTROYs.

  p4raw-id​: //depot/perl@​7991

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl 5.18.0:

Configured by doy at Sat Aug  3 17:08:22 EDT 2013.

Summary of my perl5 (revision 5 version 18 subversion 0) configuration:
   
  Platform:
    osname=linux, osvers=3.9.3-x86_64-linode33, archname=x86_64-linux
    uname='linux tozt 3.9.3-x86_64-linode33 #1 smp mon may 20 10:22:57 edt 2013 x86_64 gnulinux '
    config_args='-de -Dprefix=/home/doy/perl5/perlbrew/perls/perl-5.18 -Aeval:scriptdir=/home/doy/perl5/perlbrew/perls/perl-5.18/bin'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.8.1 20130725 (prerelease)', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/../lib /usr/lib/../lib /lib /usr/lib /lib64 /usr/lib64
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.17.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.17'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.18.0:
    /home/doy/perl5/perlbrew/perls/perl-5.18/lib/site_perl/5.18.0/x86_64-linux
    /home/doy/perl5/perlbrew/perls/perl-5.18/lib/site_perl/5.18.0
    /home/doy/perl5/perlbrew/perls/perl-5.18/lib/5.18.0/x86_64-linux
    /home/doy/perl5/perlbrew/perls/perl-5.18/lib/5.18.0
    .


Environment for perl 5.18.0:
    HOME=/home/doy
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/doy/perl5/perlbrew/bin:/home/doy/perl5/perlbrew/perls/perl-5.18/bin:/home/doy/.bin/nethack:/home/doy/.bin:/usr/local/sbin:/usr/local/bin:/usr/lib/ccache/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/vendor_perl:/usr/bin/core_perl
    PERLBREW_BASHRC_VERSION=0.64
    PERLBREW_HOME=/home/doy/.perlbrew
    PERLBREW_MANPATH=/home/doy/perl5/perlbrew/perls/perl-5.18/man
    PERLBREW_PATH=/home/doy/perl5/perlbrew/bin:/home/doy/perl5/perlbrew/perls/perl-5.18/bin
    PERLBREW_PERL=perl-5.18
    PERLBREW_ROOT=/home/doy/perl5/perlbrew
    PERLBREW_VERSION=0.64
    PERL_BADLANG (unset)
    PERL_CPANM_OPT=-q --mirror file:///home/doy/perl5/minicpan/ --mirror http://mirrors.kernel.org/cpan/ --mirror http://cpan.metacpan.org/ --prompt
    SHELL=/bin/zsh

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 16, 2013

From @cpansprout

On Thu Aug 15 16​:17​:42 2013, doy@​tozt.net wrote​:

This is a bug report for perl from doy@​tozt.net,
generated with the help of perlbug 1.39 running under perl 5.18.0.

-----------------------------------------------------------------
[Please describe your issue here]

Given this script​:

sub foo {
my ($block, $other) = @​_;

  my $got;
  die "this is clearly a bug" if $got;

  $got = $other;

  $block\->\(\);

}

{
package Foo;

  sub DESTROY \{
      :&#8203;:foo\(sub \{ \}\, 1\);
      return;
  \}

}

# "exit(0) unless fork" also triggers the bug,
# but a bare "fork" doesn't
foo(sub { my $o = bless {}, 'Foo'; exit(0) if fork }, 1);

$got is keeping its previous value when foo() is called from the
DESTROY
method.

I cannot reproduce this on darwin or linux.

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 16, 2013

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

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 16, 2013

From @iabyn

On Fri, Aug 16, 2013 at 05​:17​:33AM -0700, Father Chrysostomos via RT wrote​:

I cannot reproduce this on darwin or linux.

I can't reproduce it on linux either. Tried lots of versions, threaded /
unthreaded, DEBUGGING, -O, valgrind, address santizer.

--
Never work with children, animals, or actors.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 16, 2013

From victor@vsespb.ru

Reproduced under perl 5.10.1 (linux), but only after adding 'use
warnings' in the beginning.

got the following message​:

(in cleanup) this is clearly a bug at 2.pl line 7.

On Thu Aug 15 16​:17​:42 2013, doy@​tozt.net wrote​:

This is a bug report for perl from doy@​tozt.net,
generated with the help of perlbug 1.39 running under perl 5.18.0.

-----------------------------------------------------------------
[Please describe your issue here]

Given this script​:

sub foo {
my ($block, $other) = @​_;

  my $got;
  die "this is clearly a bug" if $got;

  $got = $other;

  $block\->\(\);

}

{
package Foo;

  sub DESTROY \{
      :&#8203;:foo\(sub \{ \}\, 1\);
      return;
  \}

}

# "exit(0) unless fork" also triggers the bug,
# but a bare "fork" doesn't
foo(sub { my $o = bless {}, 'Foo'; exit(0) if fork }, 1);

$got is keeping its previous value when foo() is called from the
DESTROY
method. This has been broken since 5.8.0, a bisect points to 840a7b7
as
where the bug was introduced​:

commit 840a7b7
Author​: Ilya Zakharevich <ilya@​math.berkeley.edu>
Date​: Mon Dec 4 19​:40​:25 2000 -0500

  Re&#8203;: \[PATCH\] The largest hoax of all times?
  Date&#8203;: Tue\, 5 Dec 2000 00&#8203;:40&#8203;:25 \-0500
  Message\-ID&#8203;: \<20001205004025\.A4050@&#8203;monk\.mps\.ohio\-state\.edu>

  Subject&#8203;: Re&#8203;: \[PATCH\] The largest hoax of all times?
  From&#8203;: Ilya Zakharevich \<ilya@&#8203;math\.ohio\-state\.edu>
  Date&#8203;: Mon\, 4 Dec 2000 23&#8203;:55&#8203;:53 \-0500
  Message\-ID&#8203;: \<20001204235553\.A1140@&#8203;monk\.mps\.ohio\-state\.edu>

  Subject&#8203;: Re&#8203;: \[PATCH\] The largest hoax of all times?
  From&#8203;: Ilya Zakharevich \<ilya@&#8203;math\.ohio\-state\.edu>
  Date&#8203;: Tue\, 5 Dec 2000 01&#8203;:28&#8203;:45 \-0500
  Message\-ID&#8203;: \<20001205012844\.A4227@&#8203;monk\.mps\.ohio\-state\.edu>

  Fix the unpredictable order of DESTROYs\.

  p4raw\-id&#8203;: //depot/perl@&#8203;7991

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags​:
category=core
severity=medium
---
Site configuration information for perl 5.18.0​:

Configured by doy at Sat Aug 3 17​:08​:22 EDT 2013.

Summary of my perl5 (revision 5 version 18 subversion 0)
configuration​:

Platform​:
osname=linux, osvers=3.9.3-x86_64-linode33, archname=x86_64-linux
uname='linux tozt 3.9.3-x86_64-linode33 #1 smp mon may 20 10​:22​:57
edt 2013 x86_64 gnulinux '
config_args='-de -Dprefix=/home/doy/perl5/perlbrew/perls/perl-5.18
-Aeval​:scriptdir=/home/doy/perl5/perlbrew/perls/perl-5.18/bin'
hint=recommended, useposix=true, d_sigaction=define
useithreads=undef, usemultiplicity=undef
useperlio=define, d_sfio=undef, uselargefiles=define,
usesocks=undef
use64bitint=define, use64bitall=define, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler​:
cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O2',
cppflags='-fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include'
ccversion='', gccversion='4.8.1 20130725 (prerelease)',
gccosandvers=''
intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define,
longdblsize=16
ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries​:
ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
libpth=/usr/local/lib /lib/../lib /usr/lib/../lib /lib /usr/lib
/lib64 /usr/lib64
libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
libc=/lib/libc-2.17.so, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.17'
Dynamic Linking​:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib
-fstack-protector'

Locally applied patches​:

---
@​INC for perl 5.18.0​:
/home/doy/perl5/perlbrew/perls/perl-
5.18/lib/site_perl/5.18.0/x86_64-linux
/home/doy/perl5/perlbrew/perls/perl-5.18/lib/site_perl/5.18.0
/home/doy/perl5/perlbrew/perls/perl-5.18/lib/5.18.0/x86_64-linux
/home/doy/perl5/perlbrew/perls/perl-5.18/lib/5.18.0
.

---
Environment for perl 5.18.0​:
HOME=/home/doy
LANG=en_US.UTF-8
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/home/doy/perl5/perlbrew/bin​:/home/doy/perl5/perlbrew/perls/perl-

5.18/bin​:/home/doy/.bin/nethack​:/home/doy/.bin​:/usr/local/sbin​:/usr/local/bin​:/usr/lib/ccache/bin​:/usr/local/sbin​:/usr/local/bin​:/usr/bin​:/usr/bin/vendor_perl​:/usr/bin/core_perl

PERLBREW\_BASHRC\_VERSION=0\.64
PERLBREW\_HOME=/home/doy/\.perlbrew
PERLBREW\_MANPATH=/home/doy/perl5/perlbrew/perls/perl\-5\.18/man

PERLBREW_PATH=/home/doy/perl5/perlbrew/bin​:/home/doy/perl5/perlbrew/perls/perl-

5.18/bin
PERLBREW_PERL=perl-5.18
PERLBREW_ROOT=/home/doy/perl5/perlbrew
PERLBREW_VERSION=0.64
PERL_BADLANG (unset)
PERL_CPANM_OPT=-q --mirror file​:///home/doy/perl5/minicpan/
--mirror http​://mirrors.kernel.org/cpan/ --mirror
http​://cpan.metacpan.org/ --prompt
SHELL=/bin/zsh

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 16, 2013

From @cpansprout

On Fri Aug 16 08​:03​:36 2013, vsespb wrote​:

Reproduced under perl 5.10.1 (linux), but only after adding 'use
warnings' in the beginning.

got the following message​:

(in cleanup) this is clearly a bug at 2.pl line 7.

I get it with warnings, too. It is hard to debug this sort of thing
when this happens (using ‘exit 0 unless fork’)​:

$ ./perl -ILib -w foo
  (in cleanup) this is clearly a bug at foo line 6.
$ gdb --args ./perl -ILib -w foo
GNU gdb 6.3.50-20050815 (Apple version gdb-1824) (Wed Feb 6 22​:51​:23
UTC 2013)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for
shared libraries ... done

(gdb) run
Starting program​: /Users/sprout/Perl/perl.git-copy/perl -ILib -w foo
Reading symbols for shared libraries ++.............................. done
  (in cleanup) this is clearly a bug at foo line 6.

Program exited normally.
(gdb) break Perl_pp_die
Breakpoint 1 at 0x1003454d0​: file pp_sys.c, line 475.
(gdb) run
Starting program​: /Users/sprout/Perl/perl.git-copy/perl -ILib -w foo

Program exited normally.
(gdb) run
Starting program​: /Users/sprout/Perl/perl.git-copy/perl -ILib -w foo
warning​: Got an error handling event​: "assertion failure on line 243 of
"/SourceCache/gdb/gdb-1824/src/gdb/macosx/macosx-nat-inferior-util.c" in
function "kern_return_t
macosx_inferior_resume_mach(macosx_inferior_status *, int)"​:
macosx_task_valid (s->task)
".
(gdb)

It exhibits the reported buggy behaviour consistently with no breakpoint.

With a breakpoint it runs to completion with no error, fails an
assertion in gdb itself, or gets EXC_BAD_ACCESS inside
__dyld__ZL18initialPoolContent (whatever that is), more or less at random.

So, whose bug *is* this?

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 16, 2013

From @cpansprout

On Fri Aug 16 08​:42​:07 2013, sprout wrote​:

On Fri Aug 16 08​:03​:36 2013, vsespb wrote​:

Reproduced under perl 5.10.1 (linux), but only after adding 'use
warnings' in the beginning.

got the following message​:

(in cleanup) this is clearly a bug at 2.pl line 7.

I get it with warnings, too. It is hard to debug this sort of thing
when this happens (using ‘exit 0 unless fork’)​:

... debugging stuff ...

So, whose bug *is* this?

I think we can disregard that. It is probably a compiler/debugger
incompatibility.

If I add ‘warn $$’ to the top of the script at change the fork statement
to ()=(fork,exit(0)), I get this​:

$ ./perl -ILib foo
23761 at foo line 1.
  (in cleanup) this is clearly a bug 23762 at foo line 8.
  (in cleanup) this is clearly a bug 23761 at foo line 8.

It appears to have something to do with fork’s return value being on the
stack when exit is called. Whichever process ends up with that (in this
case both) exhibits the bug.

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 16, 2013

From @cpansprout

On Fri Aug 16 08​:51​:24 2013, sprout wrote​:

On Fri Aug 16 08​:42​:07 2013, sprout wrote​:

On Fri Aug 16 08​:03​:36 2013, vsespb wrote​:

Reproduced under perl 5.10.1 (linux), but only after adding 'use
warnings' in the beginning.

got the following message​:

(in cleanup) this is clearly a bug at 2.pl line 7.

I get it with warnings, too. It is hard to debug this sort of thing
when this happens (using ‘exit 0 unless fork’)​:

... debugging stuff ...

So, whose bug *is* this?

I think we can disregard that. It is probably a compiler/debugger
incompatibility.

If I add ‘warn $$’ to the top of the script at change the fork statement
to ()=(fork,exit(0)), I get this​:

$ ./perl -ILib foo
23761 at foo line 1.
(in cleanup) this is clearly a bug 23762 at foo line 8.
(in cleanup) this is clearly a bug 23761 at foo line 8.

It appears to have something to do with fork’s return value being on the
stack when exit is called. Whichever process ends up with that (in this
case both) exhibits the bug.

Fatal warnings give me a segmentation violation. That may be another
bug. The stack has lots of this​:

11623 0x000000010030cec2 in Perl_die_unwind (msv=0x1057f5970) at
pp_ctl.c​:1658
#11624 0x000000010018e6e5 in Perl_vwarner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p", args=0x7fff5f814d10) at util.c​:1781
#11625 0x000000010018e8c6 in Perl_ck_warner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p") at util.c​:1757
#11626 0x000000010030cec2 in Perl_die_unwind (msv=0x1057f5940) at
pp_ctl.c​:1658
#11627 0x000000010018e6e5 in Perl_vwarner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p", args=0x7fff5f815160) at util.c​:1781
#11628 0x000000010018e8c6 in Perl_ck_warner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p") at util.c​:1757
#11629 0x000000010030cec2 in Perl_die_unwind (msv=0x1057f5910) at
pp_ctl.c​:1658
#11630 0x000000010018e6e5 in Perl_vwarner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p", args=0x7fff5f8155b0) at util.c​:1781
#11631 0x000000010018e8c6 in Perl_ck_warner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p") at util.c​:1757
#11632 0x000000010030cec2 in Perl_die_unwind (msv=0x1057f58e0) at
pp_ctl.c​:1658
#11633 0x000000010018e6e5 in Perl_vwarner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p", args=0x7fff5f815a00) at util.c​:1781

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 16, 2013

From victor@vsespb.ru

adding $SIG{__WARN__}=sub{die};

change error message to

  (in cleanup) (in cleanup) this is clearly a bug 3 9258 at
2.pl line 10.
  ...propagated at 2.pl line 3.

i.e. there is a warning, indeed.

On Fri Aug 16 08​:55​:11 2013, sprout wrote​:

On Fri Aug 16 08​:51​:24 2013, sprout wrote​:

On Fri Aug 16 08​:42​:07 2013, sprout wrote​:

On Fri Aug 16 08​:03​:36 2013, vsespb wrote​:

Reproduced under perl 5.10.1 (linux), but only after adding 'use
warnings' in the beginning.

got the following message​:

(in cleanup) this is clearly a bug at 2.pl line 7.

I get it with warnings, too. It is hard to debug this sort of thing
when this happens (using ‘exit 0 unless fork’)​:

... debugging stuff ...

So, whose bug *is* this?

I think we can disregard that. It is probably a compiler/debugger
incompatibility.

If I add ‘warn $$’ to the top of the script at change the fork statement
to ()=(fork,exit(0)), I get this​:

$ ./perl -ILib foo
23761 at foo line 1.
(in cleanup) this is clearly a bug 23762 at foo line 8.
(in cleanup) this is clearly a bug 23761 at foo line 8.

It appears to have something to do with fork’s return value being on the
stack when exit is called. Whichever process ends up with that (in this
case both) exhibits the bug.

Fatal warnings give me a segmentation violation. That may be another
bug. The stack has lots of this​:

11623 0x000000010030cec2 in Perl_die_unwind (msv=0x1057f5970) at
pp_ctl.c​:1658
#11624 0x000000010018e6e5 in Perl_vwarner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p", args=0x7fff5f814d10) at util.c​:1781
#11625 0x000000010018e8c6 in Perl_ck_warner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p") at util.c​:1757
#11626 0x000000010030cec2 in Perl_die_unwind (msv=0x1057f5940) at
pp_ctl.c​:1658
#11627 0x000000010018e6e5 in Perl_vwarner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p", args=0x7fff5f815160) at util.c​:1781
#11628 0x000000010018e8c6 in Perl_ck_warner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p") at util.c​:1757
#11629 0x000000010030cec2 in Perl_die_unwind (msv=0x1057f5910) at
pp_ctl.c​:1658
#11630 0x000000010018e6e5 in Perl_vwarner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p", args=0x7fff5f8155b0) at util.c​:1781
#11631 0x000000010018e8c6 in Perl_ck_warner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p") at util.c​:1757
#11632 0x000000010030cec2 in Perl_die_unwind (msv=0x1057f58e0) at
pp_ctl.c​:1658
#11633 0x000000010018e6e5 in Perl_vwarner (err=12, pat=0x10047f4c8
"\t(in cleanup) %-p", args=0x7fff5f815a00) at util.c​:1781

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 17, 2013

From @cpansprout

On Fri Aug 16 08​:55​:11 2013, sprout wrote​:

On Fri Aug 16 08​:51​:24 2013, sprout wrote​:

On Fri Aug 16 08​:42​:07 2013, sprout wrote​:

On Fri Aug 16 08​:03​:36 2013, vsespb wrote​:

Reproduced under perl 5.10.1 (linux), but only after adding 'use
warnings' in the beginning.

got the following message​:

(in cleanup) this is clearly a bug at 2.pl line 7.

I get it with warnings, too. It is hard to debug this sort of thing
when this happens (using ‘exit 0 unless fork’)​:

... debugging stuff ...

So, whose bug *is* this?

I think we can disregard that. It is probably a compiler/debugger
incompatibility.

If I add ‘warn $$’ to the top of the script at change the fork statement
to ()=(fork,exit(0)), I get this​:

$ ./perl -ILib foo
23761 at foo line 1.
(in cleanup) this is clearly a bug 23762 at foo line 8.
(in cleanup) this is clearly a bug 23761 at foo line 8.

It appears to have something to do with fork’s return value being on the
stack when exit is called.

No, actually it has nothing to do with fork. Just call exit(0) and you
get the bug.

exit() results in a call to die_unwind in pp_ctl.c, which calls POPSUB,
which does --CvDEPTH, so it looks as though foo is no longer being called.

Unwinding the savestack causes the anon sub’s lexicals to be freed
first, triggering another call to foo before the clearing of *its*
lexicals has happened, but after its depth has been set to 0.

Fatal warnings give me a segmentation violation. That may be another
bug.

Yes. it is​:

$ ./perl -Ilib -e 'use warnings FATAL=>"all"; DESTROY{die} bless []; exit'
Segmentation fault​: 11

I don’t see an obvious way to fix either of these bugs.

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 17, 2013

From victor@vsespb.ru

also happens even if program is not terminated at all​:

...
  eval {
  foo(sub { my $o = bless {}, 'Foo'; die}, 1);
  1;
  };
  print STDERR "Not exited\n";
  while (1) { sleep 1; };
__END__
  (in cleanup) this is clearly a bug at poc2.pl line 7.
Not exited

On Sat Aug 17 07​:04​:37 2013, sprout wrote​:

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 25, 2013

From @cpansprout

On Sat Aug 17 07​:04​:37 2013, sprout wrote​:

On Fri Aug 16 08​:55​:11 2013, sprout wrote​:

Fatal warnings give me a segmentation violation. That may be another
bug.

Yes. it is​:

$ ./perl -Ilib -e 'use warnings FATAL=>"all"; DESTROY{die} bless []; exit'
Segmentation fault​: 11

I don’t see an obvious way to fix either of these bugs.

Well I have an idea about the latter. The error in the destructor is
caught and turned into a warning. This warning is then turned into an
error again because of fatal warnings, resulting in a vicious cycle that
busts the stack.

We should simply bypass fatal warnings here. In fact, I wonder why this
is not a default warning. Should errors in destructors really be
ignored by default?

One reason I ask is that changing it only to ignore fatal warnings will
result in the warning category only being partly honoured. Removing the
category altogether (i.e., changing ‘W misc’ to ‘S’) keeps things
consistent, and makes things more correct IMO. Is it ok to do that?

(I’m still thinking about the original issue in the ticket. That’s a
tough one.)

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 25, 2013

From @doy

On Sat, Aug 24, 2013 at 07​:38​:55PM -0700, Father Chrysostomos via RT wrote​:

On Sat Aug 17 07​:04​:37 2013, sprout wrote​:

On Fri Aug 16 08​:55​:11 2013, sprout wrote​:

Fatal warnings give me a segmentation violation. That may be another
bug.

Yes. it is​:

$ ./perl -Ilib -e 'use warnings FATAL=>"all"; DESTROY{die} bless []; exit'
Segmentation fault​: 11

I don’t see an obvious way to fix either of these bugs.

Well I have an idea about the latter. The error in the destructor is
caught and turned into a warning. This warning is then turned into an
error again because of fatal warnings, resulting in a vicious cycle that
busts the stack.

It's really pretty clear that fatal warnings were never thought through
very well (see also, [perl #96332]).

We should simply bypass fatal warnings here. In fact, I wonder why this
is not a default warning. Should errors in destructors really be
ignored by default?

One reason I ask is that changing it only to ignore fatal warnings will
result in the warning category only being partly honoured. Removing the
category altogether (i.e., changing ‘W misc’ to ‘S’) keeps things
consistent, and makes things more correct IMO. Is it ok to do that?

I think this is a good idea (but yeah, also a separate bug).

-doy

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 25, 2013

From @cpansprout

On Sat Aug 24 19​:58​:41 2013, doy@​tozt.net wrote​:

On Sat, Aug 24, 2013 at 07​:38​:55PM -0700, Father Chrysostomos via RT
wrote​:

On Sat Aug 17 07​:04​:37 2013, sprout wrote​:

On Fri Aug 16 08​:55​:11 2013, sprout wrote​:

Fatal warnings give me a segmentation violation. That may be
another
bug.

Yes. it is​:

$ ./perl -Ilib -e 'use warnings FATAL=>"all"; DESTROY{die} bless
[]; exit'
Segmentation fault​: 11

I don’t see an obvious way to fix either of these bugs.

Well I have an idea about the latter. The error in the destructor
is
caught and turned into a warning. This warning is then turned into
an
error again because of fatal warnings, resulting in a vicious cycle
that
busts the stack.

It's really pretty clear that fatal warnings were never thought
through
very well (see also, [perl #96332]).

We should simply bypass fatal warnings here. In fact, I wonder why
this
is not a default warning. Should errors in destructors really be
ignored by default?

One reason I ask is that changing it only to ignore fatal warnings
will
result in the warning category only being partly honoured. Removing
the
category altogether (i.e., changing ‘W misc’ to ‘S’) keeps things
consistent, and makes things more correct IMO. Is it ok to do that?

I think this is a good idea

Implemented on the sprout/fataldestroy branch. I had to change quite a
few tests that tested explicitly for ‘no warnings "misc"’. I don’t feel
comfortable merging it without more feedback.

(but yeah, also a separate bug).

(I can’t fix, or even diagnose, bugs without finding more. :-)

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 25, 2013

From @cpansprout

On Sat Aug 17 07​:04​:37 2013, sprout wrote​:

No, actually it has nothing to do with fork. Just call exit(0) and you
get the bug.

exit() results in a call to die_unwind in pp_ctl.c, which calls POPSUB,
which does --CvDEPTH, so it looks as though foo is no longer being called.

Unwinding the savestack causes the anon sub’s lexicals to be freed
first, triggering another call to foo before the clearing of *its*
lexicals has happened, but after its depth has been set to 0.

The code in question is spread out all over the place. This piece in
pp_goto shows most clearly the difficulty here, since it is in one spot
(yes, goto exhibits the same bug)​:

  /* pop unwanted frames */

  if (ix < cxstack_ix) {
  I32 oldsave;

  if (ix < 0)
  ix = 0;
  dounwind(ix);
  TOPBLOCK(cx);
  oldsave = PL_scopestack[PL_scopestack_ix];
  LEAVE_SCOPE(oldsave);
  }

dounwind(ix) causes CvDEPTH to be decreased. LEAVE_SCOPE(oldsave) frees
the lexicals when it appears the sub is no longer active. Those
freeings can call the sub, obviously.

What makes this really tricky is that we cannot simply call LEAVE_SCOPE
first, since
• It depends on the value it got from PL_scopestack.
• PL_scopestack_ix is set by TOPBLOCK
• TOPBLOCK depends on the value of cxstack_ix.
• cxstack_ix is set by dounwind.

Trying to disentangle that (and differently for exit/die/die in
eval/last/redo) would be a nightmare.

Maybe what we need to do is put the clearing of lexicals inside POPSUB,
but that may affect sub {my $x; ... return $x}. We don’t want $x
cleared before pp_return can copy it.

This is a mess....

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Aug 27, 2013

From @cpansprout

On Sun Aug 25 08​:18​:03 2013, sprout wrote​:

This is a mess....

Fixed in commit 2537512. :-)

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Feb 19, 2016

@mauke - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this Feb 19, 2016
jkeenan added a commit to jkeenan/perl that referenced this issue Jul 13, 2020
Capture or suppress 'exiting' warnings

Former name referred to RT ticket 119311.  In the Oct 2019 transfer of
tickets to GitHub issues, the old ticket became
Perl/perl5#13170.

Update MANIFEST
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant