Beefy Boxes and Bandwidth Generously Provided by pair Networks RobOMonk
We don't bite newbies here... much
 
PerlMonks  

Re^4: Win32API::File not setting HANDLE_FLAG_PROTECT_FROM_CLOSE (sources)

by Yary (Scribe)
on Dec 05, 2012 at 13:20 UTC ( #1007287=note: print w/ replies, xml ) Need Help??


in reply to Re^3: Win32API::File not setting HANDLE_FLAG_PROTECT_FROM_CLOSE (sources)
in thread Win32API::File not setting HANDLE_FLAG_PROTECT_FROM_CLOSE

Hi & thanks for persisting. I'm going to post the working UNIX version of the entire program chain, with its debugging statements, for reference.
call_with_3.pl

#!/usr/bin/env perl use warnings; use strict; use Fcntl qw(F_GETFD F_SETFD FD_CLOEXEC); open my $fh,">&2"; unless (@ARGV && $ARGV[0] eq 'noset') { fcntl($fh, F_SETFD, ~FD_CLOEXEC) or die "Can't set flags: $!\n"; print "Set no close on exec\n"; } $ENV{myfd}=fileno($fh); system 'print_to_3.pl'; print $fh "This is to fd $ENV{myfd} from the parent\n";

print_to_3.pl

#!/usr/bin/env perl use warnings; use strict; open OUT,">&=$ENV{myfd}" or die "cannot dup $ENV{myfd}: $!\n"; print "Child opened FD $ENV{myfd}\n"; my $p=print OUT "***\nHere is data going to fd $ENV{myfd}\n***\n"; warn "return value of print=$p ($!)\n";
I'm copying the child's 3rd FD to STDERR- in real life I will want to move the child's 3rd FH to STDIN, and the child's stdin & stderr to filehandles the parent can read from, but I don't want to get bogged down in more details here.

The above is what got me wanting to set _PROTECT_FROM_CLOSE. If you run ./call_with_3.pl noset the pair of programs fail, you have to protect FD 3 from going away when the child exec's into a new process.

Windows doesn't really fork, it emulates it with a thread running a copy of the interpreter, so I can believe it won't need _PROTECT_FROM_CLOSE. On the other hand, _INHERIT is already set, hence the flags was=1 debug output, so that isn't the issue.

Here's the pair of programs modified for Windows. The outer program is most of the code already posted, with even more debug info.
call_with_3.pl

#!perl -w use strict; use Fcntl qw(F_GETFD F_SETFD FD_CLOEXEC O_TEXT); use Win32API::File qw(:Func :HANDLE_FLAG_); use Win32::Process; open my $fh,">&2"; $^F = 3; my $os_handle=GetOsFHandle($fh) or die "Can't GetOSFHandle: $^E,\nstop +ped"; #$ENV{myfd}=my $ivFD = OsFHandleOpenFd($os_handle,O_TEXT); GetHandleInformation($os_handle, my $flags); print "HANDLE_FLAG_INHERIT=",HANDLE_FLAG_INHERIT,"\n"; print "HANDLE_FLAG_PROTECT_FROM_CLOSE=",HANDLE_FLAG_PROTECT_FROM_CLOSE +,"\n"; print "flags was=$flags\n"; $flags |= HANDLE_FLAG_INHERIT|HANDLE_FLAG_PROTECT_FROM_CLOSE; print "Trying for flags=$flags\n"; SetHandleInformation($os_handle, 0x2, 0x2) or die "Can't SetHandleInfo +rmation: $^E,\nstopped"; GetHandleInformation($os_handle, my $newflags); print "flags now=$newflags\n"; $ENV{myfd}=fileno($fh); my $proc; #Win32::Process::Create($proc, $ENV{COMSPEC},"/c print_to_3.pl",1,0, " +." ) # or die "Can't run: $^E\n"; system 'print_to_3.pl'; print $fh "This is to fd $ENV{myfd} from the parent\n";

print_to_3.pl

open OUT,">&=$ENV{myfd}" or die "cannot dup $ENV{myfd}: $!\n"; print "Opened FD $ENV{myfd}\n"; $x=print OUT "***\nHere is data to FD $ENV{myfd}\n***\n"; warn "print=$x ($!)\n";


Comment on Re^4: Win32API::File not setting HANDLE_FLAG_PROTECT_FROM_CLOSE (sources)
Select or Download Code
Re^5: Win32API::File not setting HANDLE_FLAG_PROTECT_FROM_CLOSE (wrong layer)
by tye (Cardinal) on Dec 05, 2012 at 14:47 UTC

    The flags are on the OsFHandle and yet you are trying to share the Unixish 'fd'. Try $ENV{myosh} = $os_handle; instead and then open an fd and fh for that in the spawned process (via OsFHandleOpen).

    That's how I've done this successfully before.

    - tye        

      That works. Adding $ENV{myosh} = $os_handle; to the caller (also removing SetHandleInformation, it isn't needed) and rewriting print_to_3.pl as
      use Win32API::File qw(OsFHandleOpen); OsFHandleOpen(\*OUT,$ENV{myosh},"w"); $x=print OUT "***\nHere is data to OsH $ENV{myosh}\n***\n"; warn "print=$x ($!)\n" unless $x;
      works... Alas the "real" code I am dealing with that "print_to_3.pl" replaces is Unix-y C code. I have already made it use STDERR instead of its own stream, which is working well enough- if there's an error message then the stream is no good anyway, and in the usual case it's easier to manipulate STDERR .

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1007287]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (8)
As of 2014-04-19 05:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (478 votes), past polls