dagolden / Capture-Tiny

(Perl) Capture STDOUT and STDERR from Perl, XS or external programs
http://search.cpan.org/dist/Capture-Tiny/
39 stars 19 forks source link

Perl crash/hang with fork in code to capture/tee on Windows #12

Open garfieldnate opened 11 years ago

garfieldnate commented 11 years ago

I followed the breadcrumbs from Smart::Options to Module::Build::Pluggable::CPANfile to here. If the code input to one of the capture routines contains a fork, Perl crashes. Fork also makes the tee methods hang indefinitely. A simple script to illustrate:

use strict;
use warnings;
use Capture::Tiny qw(:all);

#crashes perl
my $stderr = capture_stderr {
    my $pid = fork();
    exit;
}

#blocks forever
my $stderr = tee_stderr {
    my $pid = fork();
    exit;
}

I wish I could contribute, but having gone down the rabbit hole I've found myself in the much more advanced bat cave :) All I know, from checking with print statements, is that the crash/hang occurs inside of the @result = $code->() statement, on line 363, in the _capture_tee method.

perl -V:

Summary of my perl5 (revision 5 version 16 subversion 1) configuration:

  Platform:
    osname=MSWin32, osvers=4.0, archname=MSWin32-x64-multi-thread
    uname='Win32 strawberry-perl 5.16.1.1 #1 Thu Aug  9 07:49:27 2012 x64'
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=undef
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE  -DPERL_TEXTMODE_
SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bi
tfields',
    optimize='-s -O2',
    cppflags='-DWIN32'
    ccversion='', gccversion='4.6.3', gccosandvers=''
    intsize=4, longsize=4, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='long long',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='g++', ldflags ='-s -L"C:\strawberry\perl\lib\CORE" -L"C:\strawberry\c\li
b"'
    libpth=C:\strawberry\c\lib C:\strawberry\c\x86_64-w64-mingw32\lib
    libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32
 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion
 -lodbc32 -lodbccp32 -lcomctl32
    perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladva
pi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lver
sion -lodbc32 -lodbccp32 -lcomctl32
    libc=, so=dll, useshrplib=true, libperl=libperl516.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-mdll -s -L"C:\strawberry\perl\lib\CORE" -L"C:\st
rawberry\c\lib"'

Characteristics of this binary (from libperl):
  Compile-time options: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY
                        PERLIO_LAYERS PERL_DONT_CREATE_GVSV
                        PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS
                        PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC
                        USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES
                        USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE
                        USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF
  Built under MSWin32
  Compiled at Aug  9 2012 07:55:51
  @INC:
    C:/strawberry/perl/site/lib/MSWin32-x64-multi-thread
    C:/strawberry/perl/site/lib
    C:/strawberry/perl/vendor/lib
    C:/strawberry/perl/lib
    .
dagolden commented 11 years ago

Thanks for the report. I might have to document that as unsupported. It falls under the warning about "Don't modify handles during a capture" and a fork definitely messes with the handles! :-)

garfieldnate commented 11 years ago

Maybe it would be possible to replace the default fork function with a custom one for the duration of the capture?

ambs commented 10 years ago

Although @dagolden is aware of that, just to keep this thread with all the data: this "bug" is a problem for Smoke testing under Windows.

dagolden commented 10 years ago

Note to self: the hang is at the "wait" in the tee-killing function, which blocks indefinitely. Something about the fork means the tee processes never see EOF.

wchristian commented 10 years ago

Wild speculating:

I suspect by EOF you mean closing of the relevant process.

I'd suspect in the case the issue is simply that on windows forks are not processes, but threads in the same process, meaning the tee processes would need to watch thread ids?