I have a script that opens a filehandle and then calls fork() and exec() to run a separate program for doing the reading. The trouble is that by default, Perl sets the close-on-exec flags on new filehandles. This can be changed with Fcntl:

use Fcntl; my $flags = fcntl $in, F_GETFD, 0 or die "fcntl F_GETFD: $!"; fcntl $in, F_SETFD, $flags & ~FD_CLOEXEC or die "fcntl F_SETFD: $!";

This doesn't work on Strawberry Perl on Windows, though, due to the F_GETFD macro being missing.

At Sebastian Riedel's suggestion, I tried local $^F = 10; instead. This makes Perl consider up to 10 open filehandles to be "system filehandles" which do not get the close-on-exec flag set (when using this, remember that you'll already have three filehandles open: STDIN, STDOUT, and STDERR).

This worked on Linux and Cygwin, but Strawberry Perl still failed to reopen the filedescriptor with "Bad file descriptor". This is the error you usually get when the close-on-exec flag is still set.

Strawberry Perl is built with threads:

This is perl 5, version 18, subversion 1 (v5.18.1) built for MSWin32-x +64-multi-thread

Since fork() would be emulated with threads in this case, perhaps that accounts for the difference with Cygwin?

Full example code below. The first one (fd_pass.pl) is passed a file to open and then forks off to exec the second one (fd_get.pl).

fd_pass.pl

#!/usr/bin/perl use v5.14; use warnings; #use Fcntl; my $FILE = shift or die "Need file to read\n"; # Don't set close-on-exec flag when we open a file handle local $^F = 10; say "Opening file"; open( my $in, '<', $FILE ) or die "Can't open '$FILE': $!\n"; # Clear the close-on-exec flag #my $flags = fcntl $in, F_GETFD, 0 or die "fcntl F_GETFD: $!"; #fcntl $in, F_SETFD, $flags & ~FD_CLOEXEC or die "fcntl F_SETFD: $!"; $SIG{CHLD} = 'IGNORE'; my $child_pid = fork(); if( $child_pid ) { # Parent while(1) { sleep 10 } } else { # Child say "Forking child process"; my $fd = fileno( $in ); exec( 'perl', './fd_get.pl', $fd ) or die "Could not exec: $!\n"; }

fd_get.pl

#!/usr/bin/perl use v5.14; use warnings; my $FD = shift or die "Need file descriptor\n"; open( my $in, '<&', $FD ) or die "Could not open file descriptor '$FD' +: $!\n"; while(<$in>) { chomp; say "Got in child: $_"; } close $in;

"There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.


In reply to Passing a File Descriptor to a New Process on Windows by hardburn

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.