Hi I think you should probably loop for EINTR from read() but otherwise this looks fine to me.
On Thu, Sep 18, 2014 at 07:51:37PM -0500, J Raynor wrote: > Tmux is hanging on aix, and the problem appears to be a race condition > in the implementation of forkpty. > > Aix has the behavior that, if data has been written to the slave side > of a pty but has not been read yet by the master side, then the last > close of the slave pty will hang until the data is read, or the master > is closed. > > I'm able to trigger the hang by calling splitw with a bad shell > command. What's happening is that after the call to fork in forkpty, > the child process continues and the spawned shell writes a "command > not found" message and then exits. It is able to do this before the > parent process calls close(slave) at the end of its part of forkpty. > By the time the parent calls close(slave), some data has been written > to the slave, and the parent has the last open reference to the slave > pty. So, the parent hangs in the close. > > Some type of coordination has to be done so that the parent (the tmux > server process) can't end up with the last open reference to the > slave. I've attached a patch that provides a possible solution. > diff --git a/compat/forkpty-aix.c b/compat/forkpty-aix.c > index db9c2e7..06f4706 100644 > --- a/compat/forkpty-aix.c > +++ b/compat/forkpty-aix.c > @@ -29,10 +29,13 @@ > 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_buf; > pid_t pid; > > + if (pipe(pipe_fd) == -1) > + return (-1); > + > if ((*master = open("/dev/ptc", O_RDWR|O_NOCTTY)) == -1) > return (-1); > > @@ -46,6 +49,10 @@ forkpty(int *master, unused char *name, struct termios > *tio, struct winsize *ws) > goto out; > case 0: > close(*master); > + close(pipe_fd[1]); > + > + read(pipe_fd[0], &dummy_buf, 1); > + close(pipe_fd[0]); > > fd = open(_PATH_TTY, O_RDWR|O_NOCTTY); > if (fd >= 0) { > @@ -80,13 +87,18 @@ forkpty(int *master, unused char *name, struct termios > *tio, struct winsize *ws) > dup2(slave, 2); > if (slave > 2) > close(slave); > + > return (0); > } > > close(slave); > + close(pipe_fd[0]); > + close(pipe_fd[1]); > return (pid); > > out: > + close(pipe_fd[0]); > + close(pipe_fd[1]); > if (*master != -1) > close(*master); > if (slave != -1) > ------------------------------------------------------------------------------ > Slashdot TV. Video for Nerds. Stuff that Matters. > http://pubads.g.doubleclick.net/gampad/clk?id=160591471&iu=/4140/ostg.clktrk > _______________________________________________ > tmux-users mailing list > tmux-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/tmux-users ------------------------------------------------------------------------------ Slashdot TV. Video for Nerds. Stuff that Matters. http://pubads.g.doubleclick.net/gampad/clk?id=160591471&iu=/4140/ostg.clktrk _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users