summaryrefslogtreecommitdiffstats
path: root/compat/forkpty-aix.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2014-09-22 14:07:00 +0100
committerNicholas Marriott <nicholas.marriott@gmail.com>2014-09-22 14:07:00 +0100
commit4d53fd98a67b20527718013ef52f263bf878481c (patch)
tree5b55ea7bac84d4518aeb38bd9e6d8045fb995039 /compat/forkpty-aix.c
parent938d91d2c37f8837e5e808c9315f551ac7bc4636 (diff)
Synchronize forkpty master and child to avoid hang on AIX with fast exiting
child and output left in the queue, from J Raynor.
Diffstat (limited to 'compat/forkpty-aix.c')
-rw-r--r--compat/forkpty-aix.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/compat/forkpty-aix.c b/compat/forkpty-aix.c
index db9c2e71..78e5f7e2 100644
--- a/compat/forkpty-aix.c
+++ b/compat/forkpty-aix.c
@@ -23,16 +23,20 @@
#include <stdlib.h>
#include <stropts.h>
#include <unistd.h>
+#include <errno.h>
#include "tmux.h"
pid_t
forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
{
- int slave, fd;
- char *path;
+ int slave, fd, pipe_fd[2];
+ char *path, dummy;
pid_t pid;
+ if (pipe(pipe_fd) == -1)
+ return (-1);
+
if ((*master = open("/dev/ptc", O_RDWR|O_NOCTTY)) == -1)
return (-1);
@@ -47,6 +51,13 @@ forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
case 0:
close(*master);
+ close(pipe_fd[1]);
+ while (read(pipe_fd[0], &dummy, 1) == -1) {
+ if (errno != EINTR)
+ break;
+ }
+ close(pipe_fd[0]);
+
fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);
if (fd >= 0) {
ioctl(fd, TIOCNOTTY, NULL);
@@ -80,13 +91,20 @@ forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
dup2(slave, 2);
if (slave > 2)
close(slave);
+
return (0);
}
+ close(pipe_fd[0]);
+ close(pipe_fd[1]);
+
close(slave);
return (pid);
out:
+ close(pipe_fd[0]);
+ close(pipe_fd[1]);
+
if (*master != -1)
close(*master);
if (slave != -1)