X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=-2.6 required=5.0 tests=BAYES_00,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Message-ID: <25015624.post@talk.nabble.com> Date: Mon, 17 Aug 2009 15:45:23 -0700 (PDT) From: Eric Blake To: cygwin AT cygwin DOT com Subject: popen bugs MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com popen misbehaves when various std fds are closed. Test program: #include #include #include #include #include #include #include #include static FILE *tty; static void dump (const char *s, int fd) { fprintf (tty, "%s: fd %d: %s\n", s, fd, dup2 (fd, fd) == fd ? (fcntl (fd, F_GETFD) & FD_CLOEXEC) ? "cloexec" : "open" : "closed"); } int main (int argc, char** argv) { const char *id = "child"; if (dup2 (6, 6) == 6) tty = fdopen (6, "a"); else { int fd = open ("/dev/tty", O_WRONLY|O_CREAT|O_APPEND, 0600); tty = fdopen (fcntl (fd, F_DUPFD, 6), "w"); close (fd); } assert (tty); if (argc > 1) { id = "parent"; FILE *slave = popen (argv[0], argv[1]); if (slave) { fputs ("parent ", tty); dump ("slave", fileno (slave)); } else fputs ("invalid mode to popen\n", tty); } dump (id, 0); dump (id, 1); dump (id, 2); return 0; } I ran the following (testing all combinations of read and write children, and all combinations of which std fds are closed): { for mode in r w; do echo testing $mode >&6; i=0; for closed in '' '<&-' '>&-' '<&- >&-' '2>&-' \ '<&- 2>&-' '>&- 2>&-' '<&- >&- 2>&-' ; do echo $((i++)) >&6; (eval ./foo $mode $closed); sleep 1; done; done } 6>log.txt then compared the logs between cygwin and Solaris, to spot the following bugs: When both stdin and stdout are closed and the parent is reading from the slave, the slave fails to get the write end of the pipe set to its stdout (regardless of whether stderr is also closed; cases r3 and r7 above): ./foo r <&- >&- $ ./foo r <&- >&- parent's slave: fd 0: cloexec parent: fd 0: cloexec parent: fd 1: closed parent: fd 2: open child: fd 0: closed child: fd 1: closed child: fd 2: open expected "child: fd 1: open" When stdin is closed and the parent is writing to the slave, the slave fails to get the read end of the pipe set to its stdin (regardless of whether stdout or stderr are closed, cases w1, w3, w5, and w7 above). $ ./foo w <&- parent's slave: fd 3: cloexec parent: fd 0: closed parent: fd 1: open parent: fd 2: open child: fd 0: closed child: fd 1: open child: fd 2: open expected "child: fd 0: open" -- Eric Blake -- View this message in context: http://www.nabble.com/popen-bugs-tp25015624p25015624.html Sent from the Cygwin list mailing list archive at Nabble.com. -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple