PTY: let closed master cause EOF on slave

This puts PTY on par with e.g. rs232 as well as behavior documented
for other OSes.  It is not a fix for an issue in userland, though.

- add a (minimal) test case to test77;
- fix a few other minor issues in test77.

Change-Id: I89c000921ee69dd9f5713665349c1ab1ad1dc2cc
This commit is contained in:
David van Moolenbroek 2014-08-27 14:23:52 +00:00
parent 3b4688844f
commit 673c4e01a5
2 changed files with 29 additions and 9 deletions

View file

@ -126,6 +126,7 @@ static int pty_master_close(devminor_t minor)
pp->state = 0; pp->state = 0;
} else { } else {
pp->state |= PTY_CLOSED; pp->state |= PTY_CLOSED;
tp->tty_termios.c_ospeed = B0; /* cause EOF on slave side */
sigchar(tp, SIGHUP, 1); sigchar(tp, SIGHUP, 1);
} }

View file

@ -20,7 +20,7 @@ static int sighups; /* number of SIGHUP signals received */
/* /*
* Signal handler for SIGHUP and SIGUSR1. * Signal handler for SIGHUP and SIGUSR1.
*/ */
void static void
signal_handler(int sig) signal_handler(int sig)
{ {
if (sig == SIGHUP) if (sig == SIGHUP)
@ -311,9 +311,28 @@ test77c(void)
if (write(slavefd, &c, sizeof(c)) >= 0) e(18); if (write(slavefd, &c, sizeof(c)) >= 0) e(18);
if (errno != EIO) e(19); if (errno != EIO) e(19);
if (close(slavefd) < 0) e(20); /* Reads from the slave should return EOF if the master is gone. */
if (read(slavefd, &c, sizeof(c)) != 0) e(20);
if (sigaction(SIGHUP, &oact, NULL) < 0) e(21); if (close(slavefd) < 0) e(21);
if (sigaction(SIGHUP, &oact, NULL) < 0) e(22);
}
/*
* Wait for a child process to terminate. Return 0 if the child exited without
* errors, -1 otherwise.
*/
static int
waitchild(void)
{
int status;
if (wait(&status) <= 0) return -1;
if (!WIFEXITED(status)) return -1;
if (WEXITSTATUS(status) != 0) return -1;
return 0;
} }
/* /*
@ -348,14 +367,14 @@ test77d(void)
if (open("/dev/tty", O_RDWR) >= 0) e(4); if (open("/dev/tty", O_RDWR) >= 0) e(4);
if (errno != ENXIO) e(5); if (errno != ENXIO) e(5);
exit(0); exit(errct);
case -1: case -1:
e(6); e(6);
default: default:
break; break;
} }
if (wait(NULL) <= 0) e(7); if (waitchild() < 0) e(7);
if (close(masterfd) < 0) e(8); if (close(masterfd) < 0) e(8);
@ -373,14 +392,14 @@ test77d(void)
if (open("/dev/tty", O_RDWR) < 0) e(12); if (open("/dev/tty", O_RDWR) < 0) e(12);
exit(0); exit(errct);
case -1: case -1:
e(13); e(13);
default: default:
break; break;
} }
if (wait(NULL) <= 0) e(14); if (waitchild() < 0) e(14);
if (close(masterfd) < 0) e(15); if (close(masterfd) < 0) e(15);
} }
@ -441,7 +460,7 @@ test77e(void)
if (sighups != 1) e(9); if (sighups != 1) e(9);
exit(0); exit(errct);
case -1: case -1:
e(10); e(10);
default: default:
@ -455,7 +474,7 @@ test77e(void)
/* Closing the master should now raise a SIGHUP signal in the child. */ /* Closing the master should now raise a SIGHUP signal in the child. */
if (close(masterfd) < 0) e(12); if (close(masterfd) < 0) e(12);
if (wait(NULL) <= 0) e(13); if (waitchild() < 0) e(13);
if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) e(14); if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) e(14);