Perl crash/hang with fork in code to capture/tee on Windows
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
.
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! :-)
Maybe it would be possible to replace the default fork function with a custom one for the duration of the capture?
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.
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.
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?