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

Reply via email to