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

segfault in perl_clone under ithreads and custom PerlIO layer #7805

Open
p5pRT opened this issue Feb 19, 2005 · 7 comments
Open

segfault in perl_clone under ithreads and custom PerlIO layer #7805

p5pRT opened this issue Feb 19, 2005 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 19, 2005

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

Searchable as RT34180$

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2005

From stas@stason.org

Created by stas@rabbit.stason.org

This is a bug report for perl from stas@​rabbit.stason.org,
generated with the help of perlbug 1.35 running under perl v5.8.6.

-----------------------------------------------------------------

We have yet another chicken-n-egg problem with perl_clone. If you do a
simple​:

use threads;
my $thread = threads->create(sub {}, undef)

and STDOUT is opened to some PerlIO layer, an attempt to clone it will be
performed. The problem is that this cloning happens too early​:

perl-5.8.6/sv.c​:10859​:

#ifdef PERLIO_LAYERS
  /* Clone PerlIO tables as soon as we can handle general xx_dup() */
  PerlIO_clone(aTHX_ proto_perl, param);
#endif

xx_dup() works for the core perl, but it doesn't
take into account that a custom PerlIO layer may need other bits set
in my_perl. In the above case I get a segfault because PL_defstash is
bogus. it's set only after PerlIO_clone is called. (line 10954)
I get this segfault​:

#0 0x404c8a04 in Perl_gv_fetchpv (my_perl=0x85e6540,
  nambeg=0x404939d0 "Apache​::RequestRec", add=1, sv_type=11) at gv.c​:670
#1 0x40479f37 in PerlIOApache_getarg (my_perl=0x85e6540, f=0x828634c,
  param=0xbfffe9c0, flags=1) at modperl_io_apache.c​:87
#2 0x405c55b5 in PerlIOBase_dup (my_perl=0x85e6540, f=0x83576c4, o=0x828634c,
  param=0xbfffe9c0, flags=1) at perlio.c​:2187
#3 0x405c1e50 in PerlIO_fdupopen (my_perl=0x85e6540, f=0x828634c,
  param=0xbfffe9c0, flags=1) at perlio.c​:542
#4 0x40555faf in Perl_fp_dup (my_perl=0x85e6540, fp=0x828634c, type=0 '\0',
  param=0xbfffe9c0) at sv.c​:9505
#5 0x405c22a5 in PerlIO_clone (my_perl=0x85e6540, proto=0x8abfb10,
  param=0xbfffe9c0) at perlio.c​:650
#6 0x4055a6fe in perl_clone (proto_perl=0x8abfb10, flags=2) at sv.c​:10859
#7 0x4078aa50 in Perl_ithread_create (my_perl=0x8abfb10, obj=0x0,
  classname=0x82dc948 "threads", init_function=0x8153728, params=0x815377c)
  at threads.xs​:426
#8 0x4078b3f7 in XS_threads_new (my_perl=0x8abfb10, cv=0x82f0698)
  at threads.xs​:687

the segfault happens here​:

  if (!stash)
  stash = PL_defstash;
  if (!stash || !SvREFCNT(stash)) /* symbol table under destruction */

PL_defstash == 0xabababab here

PerlIOApache_getarg happens to call gv_fetchpv which needs a valid
PL_defstash.

How do we resolve this problem?

This is not the first time we hit a segfault, due to
PerlIO+clone. Some of those are still unresolved (e.g. perl -m still
segfaults under threads)

Perl Info

Flags:
     category=core
     severity=high

Site configuration information for perl v5.8.6:

Configured by stas at Sun Nov 28 13:23:47 EST 2004.

Summary of my perl5 (revision 5 version 8 subversion 6) configuration:
   Platform:
     osname=linux, osvers=2.6.8.1-12mdk, archname=i686-linux-thread-multi
     uname='linux rabbit.stason.org 2.6.8.1-12mdk #1 fri oct 1 12:53:41 
cest 2004 i686 mobile intel(r) pentium(r) 4 - m cpu 2.00ghz unknown gnulinux '
     config_args='-des -Dprefix=/home/stas/perl/5.8.6-ithread -Dusethreads 
-Doptimize=-g -Duseshrplib -Dusedevel -Accflags=-DDEBUG_LEAKING_SCALARS'
     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 
-DDEBUG_LEAKING_SCALARS -DDEBUGGING -fno-strict-aliasing -pipe 
-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 
-I/usr/include/gdbm',
     optimize='-g',
     cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS 
-DDEBUG_LEAKING_SCALARS -DDEBUGGING -fno-strict-aliasing -pipe 
-I/usr/local/include -I/usr/include/gdbm'
     ccversion='', gccversion='3.4.1 (Mandrakelinux 10.1 3.4.1-4mdk)', 
gccosandvers=''
     intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
     d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
     ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', 
lseeksize=8
     alignbytes=4, prototype=define
   Linker and Libraries:
     ld='cc', ldflags =' -L/usr/local/lib'
     libpth=/usr/local/lib /lib /usr/lib
     libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
     perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
     libc=/lib/libc-2.3.3.so, so=so, useshrplib=true, libperl=libperl.so
     gnulibc_version='2.3.3'
   Dynamic Linking:
     dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E 
-Wl,-rpath,/home/stas/perl/5.8.6-ithread/lib/5.8.6/i686-linux-thread-multi/CORE'
     cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:



@INC for perl v5.8.6:
     /home/stas/perl/5.8.6-ithread/lib/5.8.6/i686-linux-thread-multi
     /home/stas/perl/5.8.6-ithread/lib/5.8.6
     /home/stas/perl/5.8.6-ithread/lib/site_perl/5.8.6/i686-linux-thread-multi
     /home/stas/perl/5.8.6-ithread/lib/site_perl/5.8.6
     /home/stas/perl/5.8.6-ithread/lib/site_perl
     .


Environment for perl v5.8.6:
     HOME=/home/stas
     LANG=en_GB
     LANGUAGE=en_GB:en
     LC_ADDRESS=en_CA
     LC_COLLATE=en_GB
     LC_CTYPE=en_GB
     LC_IDENTIFICATION=en_CA
     LC_MEASUREMENT=en_CA
     LC_MESSAGES=en_GB
     LC_MONETARY=en_CA
     LC_NAME=en_CA
     LC_NUMERIC=en_CA
     LC_PAPER=en_CA
     LC_SOURCED=1
     LC_TELEPHONE=en_CA
     LC_TIME=en_GB
     LD_LIBRARY_PATH (unset)
     LOGDIR (unset)
 
PATH=/usr//bin:/bin:/usr/bin:.:/usr/local/bin:/usr/X11R6/bin/:/usr/games:/home/stas/bin:/home/stas/bin:/usr/local/bin:/usr/X11R6/bin:/usr/java/j2re1.4.0/bin/
     PERLDOC_PAGER=less -R
     PERL_BADLANG (unset)
     SHELL=/bin/tcsh

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2005

From @iabyn

On Sat, Feb 19, 2005 at 02​:20​:28AM -0000, Stas Bekman wrote​:

We have yet another chicken-n-egg problem with perl_clone. If you do a
simple​:

use threads;
my $thread = threads->create(sub {}, undef)

and STDOUT is opened to some PerlIO layer, an attempt to clone it will be
performed. The problem is that this cloning happens too early​:

do you have a complete script that reproduces this?

something simple like
  binmode STDOUT, '​:utf8';
didn't segfault

--
Counsellor Troi states something other than the blindingly obvious.
  -- Things That Never Happen in "Star Trek" #16

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2005

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

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2005

From stas@stason.org

Dave Mitchell wrote​:

On Sat, Feb 19, 2005 at 02​:20​:28AM -0000, Stas Bekman wrote​:

We have yet another chicken-n-egg problem with perl_clone. If you do a
simple​:

use threads;
my $thread = threads->create(sub {}, undef)

and STDOUT is opened to some PerlIO layer, an attempt to clone it will be
performed. The problem is that this cloning happens too early​:

do you have a complete script that reproduces this?

something simple like
binmode STDOUT, '​:utf8';
didn't segfault

Under mod_perl2

package My​::Bug;

use Apache2​::RequestRec ();
use Apache2​::RequestIO ();

use Apache2​::Const -compile => qw(OK);

use threads;

sub handler {
  my $r = shift;

  my $thread = threads->create(sub {}, undef);
  $thread->join;

  $r->content_type('text/plain');
  print 'found a bug';

  return Apache2​::Const​::OK;
}

1;

and config​:

<Location /bug>
  SetHandler perl-script
  PerlResponseHandler My​::Bug
</Location>

I've attached a tarball that reproduces the problem. Assuming that you've
mod_perl2 installed, unpack it and run​:

perl Makefile.PL -httpd /home/stas/httpd/prefork/bin/httpd
make
make test
(you should get a segfault)
(adjust the path to the location of your httpd)

Thanks Dave.

--
__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http​://stason.org/ mod_perl Guide ---> http​://perl.apache.org
mailto​:stas@​stason.org http​://use.perl.org http​://apacheweek.com
http​://modperlbook.org http​://apache.org http​://ticketmaster.com

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2005

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2005

From stas@stason.org

A few other related things using APR​::PerlIO which can be used outside
mod_perl​:

#foo
use APR​::Pool;
use APR​::PerlIO;

my $pool = APR​::Pool->new;
my $filename = "/tmp/file";
open my $fh, ">​:APR", $filename, $pool or die $!;

use threads;
my $thread = threads->create(sub {}, undef);
$thread->join;

% perl-5.8.6-ithread /tmp/foo
*** glibc detected *** double free or corruption (!prev)​: 0x080f6518 ***
Abort

% perl-5.8.7-ithread /tmp/foo

so it looks like it was fixed in 5.8.7.

The following was also segfaulting with 5.8.6, but not with 5.8.7​:


use APR​::Pool;
use APR​::PerlIO;

my $pool = APR​::Pool->new;
my $filename = "/tmp/file";
close STDOUT;
open STDOUT, ">​:APR", $filename, $pool or die $!;

use threads;
my $thread = threads->create(sub {}, undef);
$thread->join;


Adding dup is still not good with 5.8.7​:


use APR​::Pool;
use APR​::PerlIO;

my $pool = APR​::Pool->new;
my $filename = "/tmp/file";
close STDOUT;
open STDOUT, ">​:APR", $filename, $pool or die $!;

open OLDOUT, ">&STDOUT" or die $!;

use threads;
my $thread = threads->create(sub {}, undef);
$thread->join;


% perl-5.8.7-ithread /tmp/foo2
leaked PerlIOAPR handle 0x812d0e8 during global destruction.
leaked PerlIOAPR handle 0x8065208 during global destruction.

So this is stilll an issue. Do you think it's a bug in perl?

--
__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http​://stason.org/ mod_perl Guide ---> http​://perl.apache.org
mailto​:stas@​stason.org http​://use.perl.org http​://apacheweek.com
http​://modperlbook.org http​://apache.org http​://ticketmaster.com

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2016

From @dcollinsn

Under perl 5.22 (mod_perl from the debian packages), Stas' third test program still segfaults​:

leaked PerlIOAPR handle 0x70008a0 during global destruction.
Warning​: unable to close filehandle properly​: Illegal seek during global destruction.
==63931== Invalid read of size 4
==63931== at 0x6375C38​: apr_file_flush (in /usr/lib/x86_64-linux-gnu/libapr-1.so.0.5.2)
==63931== by 0x6DCCB5F​: ??? (in /usr/lib/x86_64-linux-gnu/perl5/5.22/auto/APR/PerlIO/PerlIO.so)
==63931== by 0x53B74E​: Perl_PerlIO_flush (in /usr/bin/perl)
==63931== by 0x53B798​: Perl_PerlIO_flush (in /usr/bin/perl)
==63931== by 0x43EF29​: perl_destruct (in /usr/bin/perl)
==63931== by 0x41CBC2​: main (in /usr/bin/perl)
==63931== Address 0x402a108 is not stack'd, malloc'd or (recently) free'd

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