http://www.perlmonks.org?node_id=1158435

shadowsong has asked for the wisdom of the Perl Monks concerning the following question:

Dear Highly Esteemed Monks,

I would like some help in understanding why my Win32 VC2015 built perl fails at the Test Stage when attempting to install modules via cpan.

Specifically, I am currently receiving a Bad file descriptor error during the nmake test phase of the install. See below:

CPAN command excerpt

> cpan Path::Tiny Reading 'C:\Users\jndt\.cpan\Metadata' Database was generated on Mon, 21 Mar 2016 08:41:03 GMT Running install for module 'Path::Tiny' Checksum for C:\Users\jndt\.cpan\sources\authors\id\D\DA\DAGOLDEN\Path +-Tiny-0.084.tar.gz ok 'YAML' not installed, will not store persistent state Configuring D/DA/DAGOLDEN/Path-Tiny-0.084.tar.gz with Makefile.PL Checking if your kit is complete... Looks good Generating a nmake-style Makefile Writing Makefile for Path::Tiny Writing MYMETA.yml and MYMETA.json DAGOLDEN/Path-Tiny-0.084.tar.gz C:\perl-5.20.3\bin\perl.exe Makefile.PL -- OK Running make for D/DA/DAGOLDEN/Path-Tiny-0.084.tar.gz ---- Unsatisfied dependencies detected during ---- ---- DAGOLDEN/Path-Tiny-0.084.tar.gz ---- Unicode::UTF8 [requires,optional] Test::FailWarnings [build_requires,optional] Test::MockRandom [build_requires,optional] Microsoft (R) Program Maintenance Utility Version 14.00.23506.0 Copyright (C) Microsoft Corporation. All rights reserved. cp lib/Path/Tiny.pm blib\lib\Path\Tiny.pm DAGOLDEN/Path-Tiny-0.084.tar.gz "C:\Program Files\Microsoft Visual Studio 14.0\VC\bin\nmake.EXE" -- +OK Running make test Microsoft (R) Program Maintenance Utility Version 14.00.23506.0 Copyright (C) Microsoft Corporation. All rights reserved. C:\perl-5.20.3\bin\perl.exe "-MExtUtils::Command::MM" "-MTest: +:Harness" "-e" "undef *Test::Harness::Switches; test_harness(0 , 'blib\lib', 'blib\arch')" t/*.t t/00-report-prereqs.t ............. Can't dup STDOUT: Bad file descri +ptor at C:/perl-5.20.3/lib/Test/Builder.pm line 1948. Compilation failed in require at C:/perl-5.20.3/lib/Test/Builder/Modul +e.pm line 5. ...

Line 1948 of …Test/Builder.pm

My aim in asking this question is to solicit help in understanding why I'm encountering this particular error. Line 1948 of Builder.pm refers to the the first open call outlined below:

sub _open_testhandles { my $self = shift; return if $self->{Opened_Testhandles}; # We dup STDOUT and STDERR so people can change them in their # test suites while still getting normal test output. open( $Testout, ">&STDOUT" ) or die "Can't dup STDOUT: $!"; open( $Testerr, ">&STDERR" ) or die "Can't dup STDERR: $!"; $self->_copy_io_layers( \*STDOUT, $Testout ); $self->_copy_io_layers( \*STDERR, $Testerr ); $self->{Opened_Testhandles} = 1; return; }

Similar open statement that is ok

What I find baffling is that the following test code works okay:

use strict; use warnings; my $Testout; open( $Testout, ">&STDOUT" ) or die "Can't dup STDOUT: $!"; print $Testout "Hello Perl Monks!\n"; __END__

Additionally, see output of perl -V

Summary of my perl5 (revision 5 version 20 subversion 3) configuration:

  Platform:
    osname=MSWin32, osvers=6.1, archname=MSWin32-x86-multi-thread
    uname=''
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=undef
    useithreads=define, usemultiplicity=define
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cl', ccflags ='-nologo -GF -W3 -O1  -Zi -DNDEBUG -GL -DWIN32 -D_CONSOLE -DNO_STRICT -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTD
C_NO_DEPRECATE -D_WINSOCK_DEPRECATED_NO_WARNINGS  -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO',

    optimize='-O1  -Zi -DNDEBUG -GL',
    cppflags='-DWIN32'
    ccversion='19.00.23506', 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:\perl-5.20.3\lib\CORE"  -machine:x86 "/manifes
tdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b6
4144ccf1df' language='*'"'
    libpth="C:\Program Files\Microsoft Visual Studio 14.0\VC\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 libcmt.lib libvcruntime.lib lib
ucrt.lib
    perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.l
ib  netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib odbc32.lib odbccp32.lib comctl32.lib libcmt.lib libvcruntime.lib
 libucrt.lib
    libc=libucrt.lib, so=dll, useshrplib=true, libperl=perl520.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:\perl-5.20.3\lib\CORE"  -machine:x8
6 "/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyTo
ken='6595b64144ccf1df' language='*'"'


Characteristics of this binary (from libperl):
  Compile-time options: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY
                        PERLIO_LAYERS PERL_DONT_CREATE_GVSV
                        PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
                        PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS
                        PERL_MALLOC_WRAP PERL_NEW_COPY_ON_WRITE
                        PERL_PRESERVE_IVUV 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 Mar 18 2016 15:00:22
  @INC:
    C:/perl-5.20.3/site/lib
    C:/perl-5.20.3/lib
    .

Any Ideas?

Perl isn't happy with the open statement in Builder.pm, yet it's okay with an identical open statement in another test perl file??? Any help would be much appreciated.

Cheers,
Shadowsong

Replies are listed 'Best First'.
Re: Bad file descriptor error in Win32 VC2015 compiled perl-5.20.3
by syphilis (Archbishop) on Mar 21, 2016 at 23:04 UTC
    Any Ideas?

    I wonder if it's happening only under Test::Harness ?

    You could check that by cd'ing to the Path-Tiny-0.084 build directory and running:
    perl -Mblib t/00-report-prereqs.t
    Does that still produce the same error ?

    Afterthought: One thing that might serve as a perfectly acceptable workaround is, in Builder.pm's sub _open_testhandles(), to change the line:
    return if $self->{Opened_Testhandles}; to return if 1;
    Update: I've just noticed that the OP's aim is to reach an understanding of the problem - and that workaround won't help realise that understanding.

    Cheers,
    Rob

      Rob,

      Thanks for taking the time to chime in.

      It looks that way. Running perl -Mblib t\00-report-prereqs.t yields the following successful result:

      At the end of my response Re^2: Bad file descriptor error in Win32 VC2015 compiled perl-5.20.3 to BrowserUk, I outlined a bizarre observation wherein printing to STDOUT simply produced nothing

      Additionally

      From within the module directory - running perl "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib\lib', 'blib\arch')" t\00-report-prereqs.t yields the following unsuccessful result:

      >perl "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::H +arness::Switches; test_harness(0, 'blib\lib', 'blib\arch')" t\00-repo +rt-prereqs.t t\00-report-prereqs.t .. Can't dup STDOUT: Bad file descriptor at C:/ +perl-5.20.3/lib/Test/Builder.pm line 1952. Compilation failed in require at C:/perl-5.20.3/lib/Test/Builder/Modul +e.pm line 5. BEGIN failed--compilation aborted at C:/perl-5.20.3/lib/Test/Builder/M +odule.pm line 5. Compilation failed in require at C:/perl-5.20.3/lib/Test/More.pm line +23. BEGIN failed--compilation aborted at C:/perl-5.20.3/lib/Test/More.pm l +ine 23. Compilation failed in require at t\00-report-prereqs.t line 8. BEGIN failed--compilation aborted at t\00-report-prereqs.t line 8. t\00-report-prereqs.t .. Dubious, test returned 9 (wstat 2304, 0x900) No subtests run Test Summary Report ------------------- t\00-report-prereqs.t (Wstat: 2304 Tests: 0 Failed: 0) Non-zero exit status: 9 Parse errors: No plan found in TAP output Files=1, Tests=0, 0 wallclock secs ( 0.05 usr + 0.00 sys = 0.05 CPU +) Result: FAIL Failed 1/1 test programs. 0/0 subtests failed.

      Maybe the Test Harness is cocking up my STDOUT file descriptor?

      Cheers,
      Shadowsong

        Maybe the Test Harness is cocking up my STDOUT file descriptor?

        I've never managed to understand anything about problems that arise only when Test::Harness is invoked.
        (Best news would have been for you to report "Nope - makes no difference" ;-)

        perl "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib\lib', 'blib\arch')" t\00-report-prereqs.t


        A shot in the dark - does it make any difference if you remove undef *Test::Harness::Switches; from that command ?

        You mention another build of perl on another system where this problem does not arise.
        Do both systems run the same command when 'make test' is run ? (Obviously, they'll invoke different perls.)
        Do both systems run the same version of Test::Harness:
        perl -MTest::Harness -e "print $Test::Harness::VERSION"

        Cheers,
        Rob
Re: Bad file descriptor error in Win32 VC2015 compiled perl-5.20.3
by BrowserUk (Patriarch) on Mar 21, 2016 at 22:05 UTC

    My suggestion: print the value of fileno(STDOUT) just prior to the open.

    The OS error message: "Bad file descriptor"; suggests that STDOUT has been closed prior to the flow arriving at that open statement; and you can't dup a closed file handle.

    If you get nothing (undef) rather than 2, then you'll need to step back and work out where the filehandle is being closed.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.

      BrowserUk,

      Thank you very much indeed.

      I was able to use fileno to output the integer value associated with STDOUT just prior to the open call [as well as just prior to the subroutine call which contains said open call]

      modified Builder.pm with diagnostic print statements

      installation attempt which triggers the diagnostic print

      observations

      • The STDOUT file descriptor is associated with 1
      • Notice the diagnostic print is sent to STDERR? This is because attempts to send it to STDOUT resulted in nothing being displayed…
      • I have built this on a 64bit Win10 system with VC2015 RC2 without encountering this issue
      • I rebuilt perl-5.20.3 on this system using VC2015 RC2 (just to be certain I used the same tools that yielded a successful build)

      So, although the STDOUT is 1 - the fact that printing to it yields no output; signifies something is definitely wrong with it.

      Thanks again for your help - I feel much better about it now and I learned a new function.

      Cheers,
      Shadowsong