Serious thread problem? [ptsekov@gmx.net: Perl 5.8.1 crash description]

Christopher Faylor cgf@redhat.com
Thu Aug 7 22:06:00 GMT 2003


----- Forwarded message from Pavel Tsekov <ptsekov@gmx.net> -----

From: Pavel Tsekov <ptsekov@gmx.net>
To: cygwin-apps@cygwin.com
Subject: Perl 5.8.1 crash description
Date: Fri, 8 Aug 2003 00:03:52 +0200 (MEST)
Mail-Followup-To: cygwin-apps@cygwin.com

Ok, here is my description of the problem.

The following snippet of ext/thread/t/thread.t triggers
the problem:

{
    my $lock : shared;
    sub islocked {
	lock($lock);
	my $val = shift;
	my $ret;
	print $val;
	if (@_) {
	    $ret = threads->new(\&islocked, shift);
	}
	return $ret;
    }
my $t = threads->new(\&islocked, "ok 13\n", "ok 14\n");
$t->join->join;
}

Short description:

Two threads a created in this test - the first one is created
by the main thread and then as part of its execution it creates
the second thread.

On thread creation a duplication of different kind of objects is
triggered in perl_clone (). As part of perl_clone () PerlIO
objects are duplicated too. This involves duplication of the
FILE pointers used by PerlIO. The duplication is done by using
the fdopen () call.

Now, when reentrant structures are allocated as part of the
Cygwin thread creation, these structures are allocated on
the thread stack. Newlib keeps a pointer to one of this
reentrant structures in the FILE structure.

What happens is that the second thread gets a FILE object which
was returned by fdopen () to the first thread. This FILE
object has the pointer to the reentrant structure of the first
thread inside it. So when a Newlib call executed in the second
thread tries to reference the reentrant structure SIGSEGV is
generated because the first thread is no longer alive.


A GDB session showing the problem:

-> The first thread is created

Breakpoint 2, pthread::thread_init_wrapper(void*) (_arg=0x10341ee0) at
../../../../src/winsup/cygwin/thread.cc:1782
1782      pthread *thread = (pthread *) _arg;
(gdb) thr
[Current thread is 11 (thread 1460.0x4e4)]

[...]

-> Reentrant structures allocation for the first thread

1798      local_reent._clib = &local_clib;
(gdb) 
1799      local_reent._winsup = &local_winsup;
(gdb) 
1801      local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG);
(gdb) p local_reent
$1 = {_clib = 0xcff5fc, _winsup = 0xcff99c}

[...]

-> fdopen () calls for stdin and  stdout (stderr stripped to reduce
   size)
Breakpoint 3, fdopen64 (fd=0, mode=0xcfef4c "r") at
../../../../../src/newlib/libc/stdio64/fdopen64.c:118
118       return _fdopen64_r (_REENT, fd, mode);
Current language:  auto; currently c
(gdb) thr
[Current thread is 11 (thread 1460.0x4e4)]
(gdb) c
Continuing.

Breakpoint 3, fdopen64 (fd=1, mode=0xcfef4c "w") at
../../../../../src/newlib/libc/stdio64/fdopen64.c:118
118       return _fdopen64_r (_REENT, fd, mode);
(gdb) thr
[Current thread is 11 (thread 1460.0x4e4)]

[...]

-> The pointer returned by fdopen () for stdout

(gdb) 
108       return fp;
(gdb) p fp
$4 = (FILE *) 0x10143cbc
(gdb) p fp->_data
$5 = (struct _reent *) 0xcff5fc
(gdb) p fp->_file
$6 = 1
(gdb) 

-> The second thread is created

Breakpoint 2, pthread::thread_init_wrapper(void*) (_arg=0x10274eb8) at
../../../../src/winsup/cygwin/thread.cc:1782
1782      pthread *thread = (pthread *) _arg;
Current language:  auto; currently c++
(gdb) thr
[Current thread is 12 (thread 1460.0x5c0)]

[...]

-> Reentrant structures allocation for the second thread

1798      local_reent._clib = &local_clib;
(gdb) 
1799      local_reent._winsup = &local_winsup;
(gdb) 
1801      local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG);
(gdb) p local_reent
$7 = {_clib = 0xeff5fc, _winsup = 0xeff99c}

(gdb) c
Continuing.

-> fwrite () issued in the second thread triggers a crash when
   CHECK_INIT references fp->_data. As it is seen this is the
   same object returned previously by fdopen () in thread 11.
   
Program received signal SIGSEGV, Segmentation fault.
0x610cce15 in __swsetup (fp=0x10143cbc) at
../../../../../src/newlib/libc/stdio/wsetup.c:36
36        CHECK_INIT (fp);
Current language:  auto; currently c
(gdb) p fp
$8 = (FILE *) 0x10143cbc
(gdb) p fp->_data
$9 = (struct _reent *) 0xcff5fc
(gdb) p fp->_file
$10 = 1
(gdb) thread 11
Thread ID 11 not known.

I hope this helps ;)

Pavel

P.S. below you can find backtraces showing what thread
     one does when it creates the second thread.

Breakpoint 2, pthread::thread_init_wrapper(void*) (_arg=0x10274eb8) at
../../../../src/winsup/cygwin/thread.cc:1782
1782      pthread *thread = (pthread *) _arg;
(gdb) thr
[Current thread is 11 (thread 1460.0x5c0)]
(gdb) break fdopen64
Note: breakpoint 4 (disabled) also set at pc 0x610bc9e6.
Breakpoint 5 at 0x610bc9e6: file
../../../../../src/newlib/libc/stdio64/fdopen64.c, line 118.
(gdb) c
Continuing.
ok 13

Breakpoint 5, fdopen64 (fd=0, mode=0xcfef4c "r") at
../../../../../src/newlib/libc/stdio64/fdopen64.c:118
118       return _fdopen64_r (_REENT, fd, mode);
Current language:  auto; currently c
(gdb) bt
#0  fdopen64 (fd=0, mode=0xcfef4c "r") at
../../../../../src/newlib/libc/stdio64/fdopen64.c:118
#1  0x100ed084 in cygperl5_8_1!PerlIOStdio_dup () from
/tmp/build/perl/perl-5.8.1-RC4-1/buildperl/cygperl5_8_1.dll
#2  0x100ea9af in cygperl5_8_1!PerlIO_fdupopen () from
/tmp/build/perl/perl-5.8.1-RC4-1/buildperl/cygperl5_8_1.dll
#3  0x100954bd in cygperl5_8_1!Perl_fp_dup () from
/tmp/build/perl/perl-5.8.1-RC4-1/buildperl/cygperl5_8_1.dll
#4  0x100eafab in cygperl5_8_1!PerlIO_clone () from
/tmp/build/perl/perl-5.8.1-RC4-1/buildperl/cygperl5_8_1.dll
#5  0x100903a8 in perl_clone () from
/tmp/build/perl/perl-5.8.1-RC4-1/buildperl/cygperl5_8_1.dll
#6  0x00ac1c35 in threads!Perl_ithread_create () from
/usr/lib/perl5/5.8.1/cygwin-thread-multi-64int/auto/threads/threads.dll
#7  0x00ac2438 in threads!XS_threads_new () from
/usr/lib/perl5/5.8.1/cygwin-thread-multi-64int/auto/threads/threads.dll
#8  0x1007b64b in cygperl5_8_1!Perl_pp_entersub () from
/tmp/build/perl/perl-5.8
.1-RC4-1/buildperl/cygperl5_8_1.dll
#9  0x100745d9 in cygperl5_8_1!Perl_runops_standard () from
/tmp/build/perl/perl-5.8.1-RC4-1/buildperl/cygperl5_8_1.dll
#10 0x10005359 in cygperl5_8_1!Perl_call_sv () from
/tmp/build/perl/perl-5.8.1-RC4-1/buildperl/cygperl5_8_1.dll
#11 0x100050d2 in cygperl5_8_1!Perl_call_sv () from
/tmp/build/perl/perl-5.8.1-RC4-1/buildperl/cygperl5_8_1.dll
#12 0x00ac1744 in threads!Perl_ithread_run () from
/usr/lib/perl5/5.8.1/cygwin-thread-multi-64int/auto/threads/threads.dll
#13 0x61093d3f in pthread::thread_init_wrapper(void*) (_arg=0x10274eb8) at
../../../../src/winsup/cygwin/thread.cc:1823
#14 0x77e887dd in KERNEL32!GetModuleFileNameA () from
/mnt/c/WINNT/system32/kernel32.dll

-- 
COMPUTERBILD 15/03: Premium-e-mail-Dienste im Test
--------------------------------------------------
1. GMX TopMail - Platz 1 und Testsieger!
2. GMX ProMail - Platz 2 und Preis-Qualit?tssieger!
3. Arcor - 4. web.de - 5. T-Online - 6. freenet.de - 7. daybyday - 8. e-Post

----- End forwarded message -----



More information about the Cygwin-developers mailing list