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

all I/O calls that involve a path inside CLONE method during Win32 fork abort() the Perl process #13468

Open
p5pRT opened this issue Dec 12, 2013 · 1 comment

Comments

@p5pRT
Copy link

p5pRT commented Dec 12, 2013

Migrated from rt.perl.org#120767 (status was 'new')

Searchable as RT120767$

@p5pRT
Copy link
Author

p5pRT commented Dec 12, 2013

From @bulk88

Created by @bulk88

In dagolden/Path-Tiny#75 a Win32 only bug was
reported to File​::ShareDir​::ProjectDistDir. This was eventually tracked
down to a line in Path​::Tiny
-----------------
sub CLONE { require threads; $TID = threads->tid }
-----------------
That lead to dagolden/Path-Tiny#75 and seeking
my help on #p5p.

The code to reproduce the error in the tickets above is.
------------------------------------------------------------
package Foo;

sub CLONE {
  print "perl exists\n" if
  -e $^X; # abort() called on Win32, console error message from MS CRT
below
#This application has requested the Runtime to terminate it in an
unusual way.
#Please contact the application's support team for more information.
  #1; #works fine on Win32 perl
}

package main;

print "Message from master $$ pre-fork\n";
my $pid = fork();
if($pid == 0) {
  print "Message from $$\n";
  sleep 1;
  exit(0);
}
print "Message from master $$ pre-wait\n";
waitpid($pid, 0);
print "Message from master $$ post-wait\n";
------------------------------------------------------------
This code fails with
------------------------------------------------------------
This application has requested the Runtime to terminate it in an unusual
way.
Please contact the application's support team for more information.
-----------------------------------------------------------
in the console on 5.19.7 and 5.12.3. These 2 lines show either assert()
was called, or abort() was called in MS's CRT (C std lib).

Below is a callstack on a -O1 optimized perl build (not 100% accurate,
DEBUGGING/-Od shows problem better).
----------------------------------------------------------

kernel32.dll!_ExitProcess@​4()
  msvcr71.dll!__crtExitProcess(int status=2083928261) Line 463 +
0x9 C
  00000003()
  msvcr71.dll!doexit(int code=-1, int quick=1243048, int
retcaller=2083958145) Line 414 + 0x7 C
  msvcr71.dll!__crtExitProcess(int status=1243048) Line 463 + 0x9 C
  ffffffff()
  msvcr71.dll!_exit(int code=3) Line 311 + 0xd C
  msvcr71.dll!raise(int signum=22) Line 508 C
  msvcr71.dll!abort() Line 48 + 0x7 C
  perl519.dll!IPerlDir2Host(IPerlDir * piPerl=0x7c80e6cb) Line 277 +
0x13 C
  perl519.dll!PerlDirMapPathA(IPerlDir * piPerl=0x0090931c, const
char * path=0x0092f7dc) Line 1175 + 0x9 C
  perl519.dll!win32_stat(const char * path=0x0092f7dc, _stati64 *
sbuf=0x009050fc) Line 1492 + 0xe C
  perl519.dll!PerlLIOLstat(IPerlLIO * piPerl=0x009092b4, const char *
path=0x0092f7dc, _stati64 * buffer=0x009050fc) Line 1050 + 0xd C
  perl519.dll!Perl_my_stat_flags(interpreter * my_perl=0x00000017,
const unsigned long flags=0) Line 1326 + 0x1b C
  perl519.dll!Perl_pp_ftis(interpreter * my_perl=0x00904f65) Line
3092 C
  perl519.dll!Perl_runops_standard(interpreter * my_perl=0x00904fec)
Line 42 + 0x4 C
  perl519.dll!Perl_call_sv(interpreter * my_perl=0x280b4e4b, sv *
sv=0x280bc689, volatile long flags=9474844) Line 2732 + 0x1f C
  perl519.dll!perl_clone_using(interpreter * proto_perl=0x0090e4e4,
unsigned long flags=1, IPerlMem * ipM=0x00364ccc, IPerlMem *
ipMS=0x00000001, IPerlMem * ipMP=0x00000000, IPerlEnv * ipE=0x009091e0,
IPerlStdIO * ipStd=0x00909218, IPerlLIO * ipLIO=0x009092b4, IPerlDir *
ipD=0x0090931c, IPerlSock * ipS=0x00909348, IPerlProc * ipP=0x009093f8)
Line 13892 C
  perl519.dll!PerlProcFork(IPerlProc * piPerl=0x00365bf8) Line 1832
+ 0x3e C
  perl519.dll!Perl_pp_fork(interpreter * my_perl=0x003643fc) Line
4027 + 0xa C
  perl519.dll!Perl_runops_standard(interpreter * my_perl=0x003643fc)
Line 42 + 0x4 C
  perl519.dll!S_run_body(interpreter * my_perl=0x00000000, long
oldscope=1) Line 2433 + 0xa C
  perl519.dll!perl_run(interpreter * my_perl=0x003643fc) Line 2349 +
0x8 C
  perl519.dll!RunPerl(int argc=2, char * * argv=0x01362510, char * *
env=0x00362cc0) Line 270 + 0x6 C
  perl.exe!main(int argc=2, char * * argv=0x00362510, char * *
env=0x00362cc0) Line 23 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23
-----------------------------------------------------------
from a DEBUGGING perl, more detail is offered, mechanics are the same
-----------------------------------------------------------
kernel32.dll!_ExitProcess@​4()
  msvcr71.dll!__crtExitProcess(int status=2083928261) Line 463 +
0x9 C
  00000003()
  msvcr71.dll!doexit(int code=-1, int quick=456000, int
retcaller=2083958145) Line 414 + 0x7 C
  msvcr71.dll!__crtExitProcess(int status=456000) Line 463 + 0x9 C
  ffffffff()
  msvcr71.dll!_exit(int code=3) Line 311 + 0xd C
  msvcr71.dll!raise(int signum=22) Line 508 C
  msvcr71.dll!abort() Line 48 + 0x7 C
  perl512.dll!win32_checkTLS(interpreter * host_perl=0xbaadf00d)
Line 64 C++
  perl512.dll!CheckInterp(CPerlHost * host=0x00285ff0) Line 238 +
0xf C++
  perl512.dll!IPerlDir2Host(IPerlDir * piPerl=0x00286184) Line 278 +
0xe C++
  perl512.dll!PerlDirMapPathA(IPerlDir * piPerl=0x00286184, const
char * path=0x00861534) Line 1192 + 0xd C++
  perl512.dll!win32_stat(const char * path=0x00861534, _stati64 *
sbuf=0x008330bc) Line 1474 + 0x1a C
  perl512.dll!PerlLIONameStat(IPerlLIO * piPerl=0x0028611c, const
char * path=0x00861534, _stati64 * buffer=0x008330bc) Line 1067 +
0xd C++
  perl512.dll!Perl_my_stat(interpreter * my_perl=0x0083302c) Line
1321 + 0x24 C
  perl512.dll!Perl_pp_ftis(interpreter * my_perl=0x0083302c) Line
3122 + 0x9 C
  perl512.dll!Perl_runops_debug(interpreter * my_perl=0x0083302c)
Line 2049 + 0xd C
  perl512.dll!Perl_call_sv(interpreter * my_perl=0x0083302c, sv *
sv=0x0083e874, volatile long flags=6) Line 2590 + 0x36 C
  perl512.dll!perl_clone_using(interpreter * proto_perl=0x00394014,
unsigned long flags=1, IPerlMem * ipM=0x00285ff4, IPerlMem *
ipMS=0x00286010, IPerlMem * ipMP=0x0028602c, IPerlEnv * ipE=0x00286048,
IPerlStdIO * ipStd=0x00286080, IPerlLIO * ipLIO=0x0028611c, IPerlDir *
ipD=0x00286184, IPerlSock * ipS=0x002861b0, IPerlProc * ipP=0x00286260)
Line 12550 + 0x15 C
  perl512.dll!PerlProcFork(IPerlProc * piPerl=0x00285bf8) Line 1859
+ 0x65 C++
  perl512.dll!Perl_pp_fork(interpreter * my_perl=0x00394014) Line
4082 + 0x16 C
  perl512.dll!Perl_runops_debug(interpreter * my_perl=0x00394014)
Line 2049 + 0xd C
  perl512.dll!S_run_body(interpreter * my_perl=0x00394014, long
oldscope=1) Line 2308 + 0xd C
  perl512.dll!perl_run(interpreter * my_perl=0x00394014) Line 2233 +
0xd C
  perl512.dll!RunPerl(int argc=2, char * * argv=0x00282510, char * *
env=0x00282790) Line 270 + 0x9 C++
  perl.exe!main(int argc=2, char * * argv=0x00282510, char * *
env=0x00282cc0) Line 23 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23
-------------------------------------------
notice the " perl512.dll!win32_checkTLS(interpreter *
host_perl=0xbaadf00d) Line 64 C++" line

This is because CPerlHost struct's host_perl member is 0xbaadf00d. From
reading the code (not actually stepping it), it seems host_perl is
assigned to/initialized in PerlProcFork, AFTER perl_clone_using returns
back, to PerlProcFork, at
http​://perl5.git.perl.org/perl.git/blob/4b76cb9db827e0f9f047de33ae98ca8b86be8260​:/win32/perlhost.h#l1834
. TLS in the parent perl thread is is set to the new interp * and that
is a valid pointer. perl_clone_using is calling CLONE methods on
stashes. By supplying a CLONE method that does any I/O through Perl APIs
involving passing a path to perlhost/Perl Win32 OS virtualizer/fake C
std lib, the uninit host_perl member is read, compared to the valid
interp * in TLS, and this crash is triggered. Doing a "require" in the
CLONE method will also trigger this, but "-e" keeps the test script more
simple than debugging "require". This can not be reproduced on any OS
but Win32.

Perl Info

Flags:
    category=core
    severity=high

Site configuration information for perl 5.19.7:

Configured by Owner at Thu Nov 28 02:32:44 2013.

Summary of my perl5 (revision 5 version 19 subversion 7) configuration:
  Derived from: 8f47723e28b75530b743941cdd8b07f849ec48e2
  Ancestor: 1061065f7a09399eefb50e9a035502621722bcc0
  Platform:
    osname=MSWin32, osvers=5.1, archname=MSWin32-x86-multi-thread
    uname=''
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=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='cl', ccflags ='-nologo -GF -W3 -O1 -MD -Zi -DNDEBUG -G7 -GL 
-DWIN32 -D_CONSOLE -DNO_STRICT  -DPERL_TEXTMODE_SCRIPTS 
-DPERL_HASH_FUNC_ONE_AT_A_TIME -DPERL_IMPLICIT_CONTEXT 
-DPERL_IMPLICIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T',
    optimize='-O1 -MD -Zi -DNDEBUG -G7 -GL',
    cppflags='-DWIN32'
    ccversion='13.10.6030', gccversion='', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=8
    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 
-ltcg  -libpath:"c:\perl519\lib\CORE"  -machine:x86'
    libpth="C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\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 comctl32.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 comctl32.lib msvcrt.lib
    libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl519.lib
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug 
-opt:ref,icf -ltcg  -libpath:"c:\perl519\lib\CORE"  -machine:x86'

Locally applied patches:
    uncommitted-changes
    8f47723e28b75530b743941cdd8b07f849ec48e2


@INC for perl 5.19.7:
    C:/perl519/site/lib
    C:/perl519/lib
    .


Environment for perl 5.19.7:
    HOME (unset)
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=C:\perl519\bin;C:\Program Files\Microsoft Visual Studio .NET 
2003\Common7\IDE;C:\Program Files\Microsoft Visual Studio .NET 
2003\VC7\BIN;C:\Program Files\Microsoft Visual Studio .NET 
2003\Common7\Tools;C:\Program Files\Microsoft Visual Studio .NET 
2003\Common7\Tools\bin\prerelease;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32\wbem;
    PERL_BADLANG (unset)
    SHELL (unset)


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