Skip to content

Commit

Permalink
pty: fix signal delivery
Browse files Browse the repository at this point in the history
We were only getting the first signal since pselect unblocks all
signals after it is called instead of just restoring the mask.

Removed the use of pselect because it was redundant.  We were
already blocking the signals.

Also removed some of the hacks that were in place to work around
missing SIGCHLD.

Finally, added correct setting of the term window size on parent setup.
  • Loading branch information
mstory21 committed May 13, 2021
1 parent ee46e33 commit 2bd640d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 29 deletions.
5 changes: 2 additions & 3 deletions enter.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ int enter(struct entry_settings *opts)

for (;;) {

int waitflags = WEXITED | WNOHANG;
siginfo_t info;
if (parentSock < 0) {
sig_wait(&mask, &info);
Expand All @@ -284,7 +283,7 @@ int enter(struct entry_settings *opts)
continue;
}
} else {
if (!tty_parent_select(pid, &waitflags)) {
if (!tty_parent_select(pid)) {
continue;
}
}
Expand All @@ -294,7 +293,7 @@ int enter(struct entry_settings *opts)
exited. */

int rc;
while ((rc = waitid(P_ALL, 0, &info, waitflags)) != -1) {
while ((rc = waitid(P_ALL, 0, &info, WEXITED | WNOHANG)) != -1) {
if (info.si_signo != SIGCHLD) {
break;
}
Expand Down
48 changes: 23 additions & 25 deletions tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ static struct tty_parent_info_s {
fd_set rfds, wfds;
int nfds;
struct termios orig;
bool stdinIsatty;
} info = {
.termfd = -1,
.sigfd = -1,
Expand All @@ -112,50 +113,49 @@ void tty_parent_cleanup() {
if (info.termfd >= 0) {
close(info.termfd);
}
if (isatty(STDIN_FILENO)) {
if (info.stdinIsatty) {
tcsetattr(STDIN_FILENO, TCSADRAIN, &info.orig);
}
}

bool tty_handle_sig(siginfo_t *siginfo) {
if (info.termfd >= 0) return false;
if (!isatty(STDIN_FILENO)) return false;

void tty_set_winsize() {
struct winsize wsize;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, (char*) &wsize) < 0) {
err(1, "reading window size");
}
if (ioctl(info.termfd, TIOCSWINSZ, (char*) &wsize) < 0) {
err(1, "writing window size");
}
}

bool tty_handle_sig(siginfo_t *siginfo) {
switch (siginfo->si_signo) {
case SIGWINCH:
if (ioctl(STDIN_FILENO, TIOCGWINSZ, (char*) &wsize) < 0) {
err(1, "reading window size");
}
if (ioctl(info.termfd, TIOCSWINSZ, (char*) &wsize) < 0) {
err(1, "writing window size");
}
if (!info.stdinIsatty) return false;
tty_set_winsize();
return true;
}
return false;
}

bool tty_parent_select(pid_t pid, int *pwaitflags) {
bool tty_parent_select(pid_t pid) {
const size_t buflen = 1024;
char buf[buflen];
sigset_t noSignals;
sigemptyset(&noSignals);
fd_set readFds = info.rfds, writeFds = info.wfds;
bool rtn = false;

int rc = pselect(info.nfds, &readFds, NULL, NULL, NULL, &noSignals);
int rc = select(info.nfds, &readFds, NULL, NULL, NULL);
if (rc == 0) {
return false;
}
if (rc < 0) {
if (errno == EINTR) {
return false;
}
err(1, "pselect");
err(1, "select");
}
struct timespec immediate = {0};
if (pselect(info.nfds, NULL, &writeFds, NULL, &immediate, &noSignals) <= 0) {
struct timeval immediate = {0};
if (select(info.nfds, NULL, &writeFds, NULL, &immediate) < 0) {
return false;
}
if (FD_ISSET(STDIN_FILENO, &readFds) && FD_ISSET((unsigned long) info.termfd, &writeFds)) {
Expand All @@ -172,7 +172,6 @@ bool tty_parent_select(pid_t pid, int *pwaitflags) {
if (write(info.termfd, &(char){4}, 1) < 0) {
warn("writing EOT to terminal");
}
rtn = false;
}
}
if (FD_ISSET((unsigned long) info.termfd, &readFds) && FD_ISSET(STDOUT_FILENO, &writeFds)) {
Expand All @@ -186,7 +185,6 @@ bool tty_parent_select(pid_t pid, int *pwaitflags) {
warn("reading from terminal");
}
FD_CLR((unsigned long) info.termfd, &info.rfds);
rtn = true;
}
}
if (FD_ISSET((unsigned long) info.sigfd, &readFds)) {
Expand All @@ -201,16 +199,13 @@ bool tty_parent_select(pid_t pid, int *pwaitflags) {
rtn = (sigfd_info.ssi_signo == SIGCHLD);
}
}
if (!FD_ISSET((unsigned long) info.termfd, &info.rfds)) {
*pwaitflags &= ~WNOHANG;
}
return rtn;
}

void tty_parent_setup(int socket) {
// Put the parent's stdin in raw mode, except add CRLF handling.
struct termios tios;
if (isatty(STDIN_FILENO)) {
if ((info.stdinIsatty = isatty(STDIN_FILENO))) {
if (tcgetattr(STDIN_FILENO, &tios) < 0) {
err(1, "tty_parent: tcgetattr");
}
Expand All @@ -230,7 +225,7 @@ void tty_parent_setup(int socket) {
if (tcgetattr(info.termfd, &tios) < 0) {
err(1, "tty_parent: tcgetattr");
}
tios.c_oflag &= ~OPOST;
tios.c_oflag &= ~((tcflag_t){OPOST});
if (tcsetattr(info.termfd, TCSAFLUSH, &tios) < 0) {
err(1, "tty_parent: tcsetattr");
}
Expand All @@ -255,6 +250,9 @@ void tty_parent_setup(int socket) {
} else {
info.nfds = info.termfd + 1;
}
if (info.stdinIsatty) {
tty_set_winsize();
}
}

void tty_child(int socket) {
Expand Down
2 changes: 1 addition & 1 deletion tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

void tty_setup_socketpair(int *pParentSock, int *pChildSock);
void tty_parent_setup(int fd);
bool tty_parent_select(pid_t pid, int *pwaitflags);
bool tty_parent_select(pid_t pid);
void tty_child(int fd);

#endif /* !TTY_H */

0 comments on commit 2bd640d

Please sign in to comment.