Subject: Re: pipe data form windows program to cygwin program
From: "Bob Byrnes" <[email-masked]>
To: [email-masked]
Date: Thu, 28 Oct 2004 22:18:11 -0400

> | Are you *sure* that you have closed *all* of the write handles to the pipe?
> | If any write handles remain open, then EOF won't be delivered to the
> | read side of the pipe.
> 
> i think i did, but even if i didn't the fact that the program exit
> normally will close all open handles under windows, won't it ?

It's true that all open handles for the parent process will be closed
on exit.  However, if handles for the write side of the pipe were
passed to the child process, and any of them remain open, then that's
a problem.  This appears to be the case for your sample program.

Here are some suggestions:

    --  If you only need to write out some compressed data, try linking
        with zlib and calling one of the gzip functions: some examples
        are provided with the zlib source distribution.  This is simple
        (no pipes or subprocesses), efficient, and effective.

    --  If you really do need a pipe to a subprocess, consider using
        popen(), which does all of the work for you.

    --  If for some reason you need to do all of the pipe and process
        creation stuff yourself, be sure to close all of the unneeded
        file descriptors in the child process as well as in the parent
        process.  The usual technique looks something like this:

            int pfds[2];    // pipe file descriptors

            pipe(pfds);     // make the pipe

            if (fork() == 0) {
                // child

                // connect stdin to read side of pipe
                dup2(pfds[0], STDIN_FILENO);

                // close unneeded pipe descriptors
                close(pfds[0]);
                close(pfds[1]);

                execlp("gzip", ...);
            } else {
                // parent

                // connect stdout to write side of pipe
                dup2(pfds[1], STDOUT_FILENO);

                // close unneeded pipe descriptors
                close(pfds[0]);
                close(pfds[1]);

                // write to stdout
                // close stdout, or exit
            }

        Alternately, the parent could just write to pfds[1], the write side
        of the pipe, if you don't want or need to mess with stdout.  But it's
        still important to close pfds[0], the read side of the pipe, in the
        parent process.

        Either way, there are no stray open file descriptors for the pipe
        in any process, so when the parent closes the write side of the pipe,
        the child should see EOF on the read side.

One final suggestion: I'd try to avoid mixing the win32 and posix APIs.
Life is complicated enough without trying to deal with win32 HANDLEs
and posix (int) file descriptors at the same time, or using functions
like DuplicateHandle() and dup2() in the same program.

HTH ...

--
Bob

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/