This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

popen bugs


popen misbehaves when various std fds are closed.

Test program:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/file.h>
#include <unistd.h>
#include <assert.h>

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]