From: ian AT cygnus DOT com (Ian Lance Taylor) Subject: Re: tty.cc fix. 16 Feb 1998 07:44:38 -0800 Message-ID: <199802161528.KAA18780.cygnus.cygwin32.developers@subrogation.cygnus.com> References: <01BD3AC4 DOT 7157C360 AT gater DOT krystalbank DOT msk DOT ru> Reply-To: cygwin32-developers AT cygnus DOT com To: sos AT prospect DOT com DOT ru Cc: cygwin32-developers AT cygnus DOT com From: Sergey Okhapkin Date: Mon, 16 Feb 1998 10:20:01 +0300 Ian Lance Taylor wrote: > From: Sergey Okhapkin > Date: Sun, 15 Feb 1998 19:35:16 +0300 > > tty.cc (fhandler_tty_slave::open): call DuplicateHandle() instead of copying. > > This patch looks wrong. It looks like it will break the EOF handling. > You have to remember that the whole point of the handle manipulation > in tty.cc is so that when the slave is closed, the pipe is closed. If > there is somewhere I need to add comments, please let me know. The code in fhandler_tty_slave::close() closes _both_ fhandler's internal handles and ttyp pointed. I see no difference in expect's behavior with and without this patch, but with this patch it's safe to open/close tty slave in pty_master owner process. I guess I don't understand this. I thought it was already safe for the master to open and close the tty slave, particularly with the patch I checked in a few days ago. Can you give an example of a program which fails without this patch? I've appended one simple pty testing program I use. It works on Unix, and needs to continue to work on cygwin32. When it works, it should print the output of stty. Ian #include #include #include #include #include #include #include #include #include #if ! defined (__CYGWIN32__) && ! defined (__linux__) #include #endif extern char *ptsname (int); static void die (const char *s, int status) { perror (s); exit (status); } static void do_once () { int om; const char *slave; struct stat sb; pid_t child; char b; int c; int status; #ifndef __linux__ om = open ("/dev/ptmx", O_RDWR); if (om < 0) die ("/dev/ptmx", 1); if (grantpt (om) < 0) die ("grantpt", 2); if (unlockpt (om) < 0) die ("unlockpt", 3); slave = ptsname (om); if (slave == NULL) die ("ptsname", 4); #else /* __linux__ */ int i; char ab[20]; for (i = 0; i < 16; i++) { struct stat st; sprintf (ab, "/dev/ptyp%x", i); if (stat (ab, &st) < 0) die ("pty stat", 30); om = open (ab, O_RDWR); if (om >= 0) { printf ("Using %s\n", ab); sprintf (ab, "/dev/ttyp%x", i); slave = ab; break; } } #endif /* __linux__ */ if (stat (slave, &sb) < 0) die ("stat", 31); child = fork (); if (child < 0) die ("fork", 5); if (child == 0) { int os; if (close (0) < 0 || close (1) < 0 || close (2) < 0 || close (om) < 0) die ("close", 6); if (setsid () < 0) die ("setsid", 13); os = open (slave, O_RDWR); if (os < 0) die (slave, 7); if (os != 0) die ("unexpected os", 8); #if ! defined (__CYGWIN32__) && ! defined (__linux__) if (ioctl (os, I_PUSH, "ptem") < 0) die ("ptem", 90); if (ioctl (os, I_PUSH, "ldterm") < 0) die ("ldterm", 91); #if 0 if (ioctl (os, I_PUSH, "ttcompat") < 0) die ("ttcompat", 92); #endif #endif #ifdef TIOCSCTTY if (ioctl (os, TIOCSCTTY, NULL) < 0) die ("TIOCSCTTY", 12); #endif if (dup2 (os, 1) < 0 || dup2 (os, 2) < 0) die ("dup2", 10); printf ("About to execlp\n"); fflush (stdout); execlp ("stty", "stty", "-a", NULL); die ("execlp", 11); } printf ("child pid is %d\n", (int) child); fflush (stdout); while ((c = read (om, &b, 1)) == 1) putchar (b); fflush (stdout); if (c < 0) { #ifdef __linux__ if (errno != EIO) #endif die ("read", 20); } if (waitpid (child, &status, 0) < 0) die ("waitpid", 21); if (WIFEXITED (status)) printf ("child exited with status %d\n", WEXITSTATUS (status)); else if (WIFSIGNALED (status)) printf ("child died with signal %d%s\n", WTERMSIG (status), (status & 0200) != 0 ? " (core dumped)" : ""); else printf ("unrecognized status %d\n", status); } int main () { do_once (); #if 0 printf ("\n"); do_once (); #endif exit (0); }