======================================================================== IPC::ChildSafe ======================================================================== Copyright (c) 1997-2001 David Boyce (dsbperl@cleartool.com). All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. DESCRIPTION ----------- This distribution contains a C API for controlling a co-process as well as a Perl module which drives the C API. It's not necessary to use the Perl wrapper; the C API can be called directly from C code if you prefer. But generally it can be thought of as a Perl module with an XS back end. See the pod documentation at the bottom of ChildSafe.pm for usage details ("perldoc IPC::ChildSafe" after installing). There's also a subclass IPC::ClearTool included in the package, as described below. This has its own README and POD. LATEST VERSION -------------- If there's a newer version of this package it should be on CPAN (e.g. http://www.perl.com/CPAN-local/modules/by-module/IPC/DSB/). Or you can reach the author at dsbperl@cleartool.com. MOTIVATION ---------- This was written to address the "deadlock problem" inherent in most coprocessing designs such as Perl's IPC::Open2 and IPC::Open3. These contain warnings such as this in their documentation: ... this is very dangerous as you may block forever. It assumes it's going to talk to something like bc, both writing to it and reading from it. This is presumably safe because you "know" that commands like bc will read a line at a time and output a line at a time ... or this, from perlipc(1): ... the problem with this is that Unix buffering is really going to ruin your day ... very few Unix commands are designed to operate over pipes, so this seldom works unless you yourself wrote the program on the other end of the double-ended pipe. Want even more quotes (from Tom Christiansen)? ... I strongly advise against using IPC::Open2 for almost anything, even though I'm its author. UNIX buffering will just drive you up the wall. You'll end up quite disappointed. It's better to use temp files as we did back in the code examples in section 9 if you really want to deal with an external process in which you wish to control both its input and its output. ... this approach won't work because in general, you can't control your child processes notions of buffering, which are entirely useless for simulating interactive work as you're attempting here. The only programs this works on are ones that are designed for it, like dc. There aren't many system programs like it. The basic problem is this: once you've sent a command to a child process, how can you know - synchronously - when the output resulting from this command has finished? If you do blocking reads from the child and make the mistake of issuing one too many, you'll block forever. If you do non-blocking reads you won't hang but you'll never be sure you've gotten all the output. The traditional solution is to let the child die after each command as is done by backquotes; the read will unblock and return EOF when the command is done and the child has died, but it's this inefficiency (a fork/exec for every command) that we're trying to get around. This implementation solves the problem, at least for a subset of possible child programs, by using a little trick: it sends a 2nd (trivial) command down the pipe right in back of every real command. When we see the the output of this special command in the return pipe, we know the real command is done. The other value IPC::ChildSafe adds over simpler packages such as Open2/Open3 is that it allows you to register a "discriminator function". This typically would apply a regular expression to any output emerging from the stderr pipe (and optionally the stdout pipe) and return a derived "exit status". For instance, if the child program is well enough written that all error messages match the pattern /Error:/, then the discriminator can simply watch for this in the stderr pipe and return the number of times it occurs for each command (and in fact that's what the default discriminator does). Thus, although a real exit status cannot be determined (after all, the child hasn't exited!), we can generally come up with a regexp to fake it reliably. I originally wrote this to control a program called cleartool, which is part of a product called ClearCase (http://www.rational.com). But while it's known to be useful with cleartool, there are presumably other applications which could work in this mode as well. Thus, all presumptions about cleartool have been abstracted into a subclass called IPC::ClearTool. IPC::ChildSafe itself should work with any "well-behaved" command-line application, where well-behaved is defined as: reads stdin, writes stdout, sends errors to stderr, and has a trivial command with a reliable one-line output string. Using the shell as an example, the trivial command would be "echo FOO" and the reliable output would of course be "FOO". DESIGN ------ It may be possible to solve the same basic problem using the Expect.pm Perl module (or Expect itself), or to code something up directly in Perl, perhaps on top of IPC::Open3. I chose to do it in C with a Perl interface because I needed both API's. I'm also sure this same technique could be implemented in pure Perl; it would have a slightly higher startup overhead but probably not much. As noted, at one time I needed the C interface too. INSTALLING ---------- Installation consists of the usual sequence of commands: perl Makefile.PL make make test make install TESTED PLATFORMS ---------------- The bulk of my testing has been on Solaris 2.5.1 and 7 and Perl 5.004_04 and 5.005_03, though as of version 2.30 it's known to work on Redhat Linux 6.0 as well. CPAN-testers say it works on HP-UX 10 too. The C code has also been tested briefly on SGI IRIX 5.3 and AIX 4.2 systems. The Perl module requires Perl 5.004 or above, due to dependence on wantarray() semantics which were added in that release. There are presumably other dependencies on 5.004. I haven't attempted to use ChildSafe on Windows NT. I'm sure the Perl code would be easy to port, and SWIG is reputed to work with NT. I really don't know how similar the semantics of pipes, stdio, etc. are on NT so the C code is a mystery, and of course fork() is always problematical on NT. I assume it's portable to NT with some unknown amount of effort given that many far more ambitious tools are ported. HOWEVER - note that as of version 3.01, B _does_ work on Windows NT as long as you have ClearCase 3.2.1 or above. That's because IPC::ClearTool has been modified to use the ClearCase COM interface on Windows and thus doesn't need the C code. See the PODs for IPC::ClearTool. If you have ClearCase you can use "omake -EN" to build perl modules on Windows. SWIG ---- The Perl-C wrappers for version up to 3.* were generated with SWIG1.1p3 and then modified somewhat by hand. As of version 4.00 there's a new handwritten XS interface contributed by Marek Rouchal. This requires Perl 5.6.0 though it could be backported to 5.005 or even 5.004 by someone knowledgeable about XS if need be. COMPILATION ----------- The C code has been built standalone on a number of platforms with a number of compilers and thus is pretty standardly portable. By default Perl will try to build it with the same compiler it was built with. FEEDBACK -------- Feel free to provide feedback on any rough edges you may find. Also, if you port this to other platforms (especially Windows) or enhance it significantly, you have at least a moral obligation to send those changes back to me at the above address. TIA.