Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Win32::Process::Create and IO::Select bad interaction

by clintp (Curate)
on Jan 09, 2003 at 15:40 UTC ( [id://225560]=perlquestion: print w/replies, xml ) Need Help??

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

I've had enough trying to figure out this bug and am ready to throw in the towel. As a last resort, I thought I'd ask here.

At this url (bundle.tar, 39K) is a cut-down version of the problem. Too much code to post, I'll give an walkthrough on creating the bug momentarily.

The problem is this: I've got multiple incoming sockets (IO::Socket::INET) that I'm managing I/O using select (IO::Select), when I have the listening program call Win32::Process::Create all of the *already established* sockets stop working. They don't report an error, it's just that select() on them stops working. It doesn't seem to matter what the program Win32::Process:Create calls actually does (the .exe included is a "Hello, world") it always causes this.

From what I've read, the third flag to W:P:C is supposed to control file descriptor inheritance by children, but I can't get it to work one way or the other and it may not even be the problem. If this were Unix, it'd feel like a child-closing-parent's-descriptors problem but I'm not entirely sure how Win32 is handling all of this.

So to re-create the bug, do this:

  1. Unpack the tar bundle noted above.
  2. Start the program "testcase.pl". It's going to create "logfile" and update it as it goes along. No other output from "testcase.pl" is really important...
  3. Start a "tail -f logfile" or the equivalent for your OS and toolset. This is what to watch.
  4. Start a copy of "logstuff.pl". This will continually send stuff over an open socket to testcase.pl, which you can watch in the logfile.
  5. Once that's going, wait a few seconds and start "client.pl". This will send a 1-time request to testcase.pl to call an external program. (It'll probably report an "Err: No output", don't sweat it.)
And what you'll see in the logfile is a continuous stream of input from the logstuff.pl program, until the client.pl program runs and finishes. At that point testcase.pl stops receiving input, even though it's still checking the socket with select.

If you start multiple logstuff.pl instances, this doesn't happen. They can connect, disconnect, etc... without problem.

And once testcase.pl has (buggily) dropped all of the other incoming sockets, re-establishing new connections work fine. The prior ones are still ignored however.

If anyone knows the reason for this nonsense between select()/W:P:C I'd love to know the answer. I've searched the newsgroups and documentation and I'm resonably sure there's not an obvious answer. And I don't *think* I've got a bug in my code because I've marked everywhere I'm opening/closing/reading/writing sockets and I'm sure I haven't accidentally killed something.

Thank you for your time!

PS: Keep your style nits to yourself, remember this is a stripped down/test case version of something much larger.
  • Comment on Win32::Process::Create and IO::Select bad interaction

Replies are listed 'Best First'.
Re: Win32::Process::Create and IO::Select bad interaction (SetHandleInformation)
by tye (Sage) on Jan 09, 2003 at 16:59 UTC

    Like in Unix, each file handle also has a bit saying whether or not it should be inheritted by another program.

    In Unix it is called the "close-on-exec flag", can be controlled by fcntl() with F_SETFD, and (as the name implies) takes effect on exec since a forked child always inherits all open file handles.

    In Windows it is just the "inherit flag" for the file handle, is initially set by the bInheritHandle field of the SECURITY_ATTRIBUTES struct argument to CreateFile() (and defaults to "don't inherit" if this argument is NULL), can be changed using SetHandleInformation() with HANDLE_FLAG_INHERIT, and takes effect when a new process is created [for example, via CreateProcess()].

    If you create a process with the bInheritHandles parameter of CreateProcess() specified as TRUE, then that process will inherit only those handles that have their "inherit bit" set to TRUE. If you specify bInheritHandles as FALSE, then no handles are inheritted.

    You should already have Win32API::File on your system so you can use SetHandleInformation() via it.

                    - tye
Re: Win32::Process::Create and IO::Select bad interaction
by clintp (Curate) on Jan 09, 2003 at 18:22 UTC
    As it turns out, it wasn't the inherit bit (as tye suggested) or a child-inheritance problem at all. Win32 by default won't let processes created with ProcessCreate() inherit sockets in a straightforward way, they have to be passed externally through other means.

    Through suggestions given by others reading this node, I tried isolating exactly when the sockets started getting ignored. So I tried POD'ing out all of the shutdown routines. And it was this bit of code here near line 244 in testcase.pl:

    close($writer); print LOG "Deleting finished $writer\n" if $debug; delete $pool{"$writer"}; $pool_sel->remove($writer);
    IO::Select->remove() on an already-closed descriptor seems to alter another descriptor in unknown ways. So it turns out that the file descriptor being affected by remove and the one being closed in the above example *aren't* the same descriptor. The simple fix is:
    $pool_sel->remove($writer); close($writer); print LOG "Deleting finished $writer\n" if $debug; delete $pool{"$writer"};
    Which solves the problem nicely. The earlier opened descriptors stay open like they should.

    I'm unclear as to whether that's a bug in Perl or IO::Select. There are open bugs in Win32 Perl having to do with file descriptor mixups during process creation, so I wouldn't doubt that this might also be another one.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://225560]
Approved by particle
Front-paged by tye
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (3)
As of 2024-04-20 13:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found