|
|
| |
IPC::Run::Win32Helper(3) |
User Contributed Perl Documentation |
IPC::Run::Win32Helper(3) |
IPC::Run::Win32Helper - helper routines for IPC::Run on Win32 platforms.
use IPC::Run::Win32Helper; # Exports all by default
IPC::Run needs to use sockets to redirect subprocess I/O so that the
select() loop will work on Win32. This seems to only work on WinNT and
Win2K at this time, not sure if it will ever work on Win95 or Win98. If you
have experience in this area, please contact me at barries@slaysys.com,
thanks!.
- optimize()
- Most common incantations of "run()"
(not "harness()",
"start()", or
"finish()") now use temporary files to
redirect input and output instead of pumper processes.
Temporary files are used when sending to child processes if
input is taken from a scalar with no filter subroutines. This is the
only time we can assume that the parent is not interacting with the
child's redirected input as it runs.
Temporary files are used when receiving from children when
output is to a scalar or subroutine with or without filters, but only if
the child in question closes its inputs or takes input from unfiltered
SCALARs or named files. Normally, a child inherits its STDIN from its
parent; to close it, use "0<&-" or the
"noinherit => 1" option. If data is
sent to the child from CODE refs, filehandles or from scalars through
filters than the child's outputs will not be optimized because
"optimize()" assumes the parent is
interacting with the child. It is ok if the output is filtered or
handled by a subroutine, however.
This assumes that all named files are real files (as opposed
to named pipes) and won't change; and that a process is not
communicating with the child indirectly (through means not visible to
IPC::Run). These can be an invalid assumptions, but are the 99% case.
Write me if you need an option to enable or disable optimizations; I
suspect it will work like the
"binary()" modifier.
To detect cases that you might want to optimize by closing
inputs, try setting the "IPCRUNDEBUG"
environment variable to the special
"notopt" value:
C:> set IPCRUNDEBUG=notopt
C:> my_app_that_uses_IPC_Run.pl
- optimizer() rationalizations
- Only for that limited case can we be sure that it's ok to batch all the
input in to a temporary file. If STDIN is from a SCALAR or from a named
file or filehandle (again, only in
"run()"), then outputs to CODE refs are
also assumed to be safe enough to batch through a temp file, otherwise
only outputs to SCALAR refs are batched. This can cause a bit of grief if
the parent process benefits from or relies on a bit of "early
returns" coming in before the child program exits. As long as the
output is redirected to a SCALAR ref, this will not be visible. When
output is redirected to a subroutine or (deprecated) filters, the
subroutine will not get any data until after the child process exits, and
it is likely to get bigger chunks of data at once.
The reason for the optimization is that, without it,
"pumper" processes are used to overcome the inconsistencies of
the Win32 API. We need to use anonymous pipes to connect to the child
processes' stdin, stdout, and stderr, yet select() does not work
on these. select() only works on sockets on Win32. So for each
redirected child handle, there is normally a "pumper" process
that connects to the parent using a socket--so the parent can
select() on that fd--and to the child on an anonymous pipe--so
the child can read/write a pipe.
Using a socket to connect directly to the child (as at least
one MSDN article suggests) seems to cause the trailing output from most
children to be lost. I think this is because child processes rarely
close their stdout and stderr explicitly, and the winsock dll does not
seem to flush output when a process that uses it exits without
explicitly closing them.
Because of these pumpers and the inherent slowness of Win32
CreateProcess(), child processes with redirects are quite slow to
launch; so this routine looks for the very common case of
reading/writing to/from scalar references in a run() routine and
converts such reads and writes in to temporary file reads and
writes.
Such files are marked as FILE_ATTRIBUTE_TEMPORARY to increase
speed and as FILE_FLAG_DELETE_ON_CLOSE so it will be cleaned up when the
child process exits (for input files). The user's default permissions
are used for both the temporary files and the directory that contains
them, hope your Win32 permissions are secure enough for you. Files are
created with the Win32API::File defaults of
FILE_SHARE_READ|FILE_SHARE_WRITE.
Setting the debug level to "details" or
"gory" will give detailed information about the optimization
process; setting it to "basic" or higher will tell whether or
not a given call is optimized. Setting it to "notopt" will
highlight those calls that aren't optimized.
- win32_parse_cmd_line
-
@words = win32_parse_cmd_line( q{foo bar 'baz baz' "bat bat"} );
returns 4 words. This parses like the bourne shell (see the
bit about shellwords() in Text::ParseWords), assuming we're
trying to be a little cross-platform here. The only difference is that
"\" is *not* treated as an escape except when it precedes
punctuation, since it's used all over the place in DOS path specs.
TODO: globbing? probably not (it's unDOSish).
TODO: shebang emulation? Probably, but perhaps that should be
part of Run.pm so all spawned processes get the benefit.
LIMITATIONS: shellwords dies silently on malformed input
like
a\"
- win32_spawn
- Spawns a child process, possibly with STDIN, STDOUT, and STDERR (file
descriptors 0, 1, and 2, respectively) redirected.
LIMITATIONS.
Cannot redirect higher file descriptors due to lack of support
for this in the Win32 environment.
This can be worked around by marking a handle as inheritable
in the parent (or leaving it marked; this is the default in perl),
obtaining it's Win32 handle with
"Win32API::GetOSFHandle(FH)" or
"Win32API::FdGetOsFHandle($fd)" and
passing it to the child using the command line, the environment, or any
other IPC mechanism (it's a plain old integer). The child can then use
"OsFHandleOpen()" or
"OsFHandleOpenFd()" and possibly
"<open FOO
""&BAR">> or
"<open FOO ""&$fd>>
as need be. Ach, the pain!
Remember to check the Win32 handle against
INVALID_HANDLE_VALUE.
Barries Slaymaker <barries@slaysys.com>. Funded by Perforce Software, Inc.
Copyright 2001, Barrie Slaymaker, All Rights Reserved.
You may use this under the terms of either the GPL 2.0 or the
Artistic License.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |