mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Move all calls to fcntl(...O_NONBLOCK) into a function and clear the
flag on the stdio file descriptors before closing them (fixes things like "tmux ls && cat").
This commit is contained in:
		
							
								
								
									
										7
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								client.c
									
									
									
									
									
								
							@@ -54,7 +54,7 @@ client_connect(char *path, int start_server)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_un	sa;
 | 
			
		||||
	size_t			size;
 | 
			
		||||
	int			fd, mode;
 | 
			
		||||
	int			fd;
 | 
			
		||||
 | 
			
		||||
	memset(&sa, 0, sizeof sa);
 | 
			
		||||
	sa.sun_family = AF_UNIX;
 | 
			
		||||
@@ -84,10 +84,7 @@ client_connect(char *path, int start_server)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(fd, F_GETFL)) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	setblocking(fd, 0);
 | 
			
		||||
	return (fd);
 | 
			
		||||
 | 
			
		||||
failed:
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	char			*command;
 | 
			
		||||
	int			 old_fd, pipe_fd[2], null_fd, mode;
 | 
			
		||||
	int			 old_fd, pipe_fd[2], null_fd;
 | 
			
		||||
 | 
			
		||||
	if ((c = cmd_find_client(ctx, NULL)) == NULL)
 | 
			
		||||
		return (-1);
 | 
			
		||||
@@ -127,10 +127,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
		    NULL, NULL, cmd_pipe_pane_error_callback, wp);
 | 
			
		||||
		bufferevent_enable(wp->pipe_event, EV_WRITE);
 | 
			
		||||
 | 
			
		||||
		if ((mode = fcntl(wp->pipe_fd, F_GETFL)) == -1)
 | 
			
		||||
			fatal("fcntl failed");
 | 
			
		||||
		if (fcntl(wp->pipe_fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
			fatal("fcntl failed");
 | 
			
		||||
		setblocking(wp->pipe_fd, 0);
 | 
			
		||||
		return (0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								job.c
									
									
									
									
									
								
							@@ -137,7 +137,7 @@ job_free(struct job *job)
 | 
			
		||||
int
 | 
			
		||||
job_run(struct job *job)
 | 
			
		||||
{
 | 
			
		||||
	int	nullfd, out[2], mode;
 | 
			
		||||
	int	nullfd, out[2];
 | 
			
		||||
 | 
			
		||||
	if (job->fd != -1 || job->pid != -1)
 | 
			
		||||
		return (0);
 | 
			
		||||
@@ -177,10 +177,7 @@ job_run(struct job *job)
 | 
			
		||||
		close(out[1]);
 | 
			
		||||
 | 
			
		||||
		job->fd = out[0];
 | 
			
		||||
		if ((mode = fcntl(job->fd, F_GETFL)) == -1)
 | 
			
		||||
			fatal("fcntl failed");
 | 
			
		||||
		if (fcntl(job->fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
			fatal("fcntl failed");
 | 
			
		||||
		setblocking(job->fd, 0);
 | 
			
		||||
 | 
			
		||||
		if (job->event != NULL)
 | 
			
		||||
			bufferevent_free(job->event);
 | 
			
		||||
 
 | 
			
		||||
@@ -53,13 +53,9 @@ void
 | 
			
		||||
server_client_create(int fd)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	int		 mode;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(fd, F_GETFL)) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	setblocking(fd, 0);
 | 
			
		||||
 | 
			
		||||
	c = xcalloc(1, sizeof *c);
 | 
			
		||||
	c->references = 0;
 | 
			
		||||
@@ -124,16 +120,22 @@ server_client_lost(struct client *c)
 | 
			
		||||
	if (c->flags & CLIENT_TERMINAL)
 | 
			
		||||
		tty_free(&c->tty);
 | 
			
		||||
 | 
			
		||||
	if (c->stdin_fd != -1)
 | 
			
		||||
	if (c->stdin_fd != -1) {
 | 
			
		||||
		setblocking(c->stdin_fd, 1);
 | 
			
		||||
		close(c->stdin_fd);
 | 
			
		||||
	}
 | 
			
		||||
	if (c->stdin_event != NULL)
 | 
			
		||||
		bufferevent_free(c->stdin_event);
 | 
			
		||||
	if (c->stdout_fd != -1)
 | 
			
		||||
	if (c->stdout_fd != -1) {
 | 
			
		||||
		setblocking(c->stdout_fd, 1);
 | 
			
		||||
		close(c->stdout_fd);
 | 
			
		||||
	}
 | 
			
		||||
	if (c->stdout_event != NULL)
 | 
			
		||||
		bufferevent_free(c->stdout_event);
 | 
			
		||||
	if (c->stderr_fd != -1)
 | 
			
		||||
	if (c->stderr_fd != -1) {
 | 
			
		||||
		setblocking(c->stderr_fd, 1);
 | 
			
		||||
		close(c->stderr_fd);
 | 
			
		||||
	}
 | 
			
		||||
	if (c->stderr_event != NULL)
 | 
			
		||||
		bufferevent_free(c->stderr_event);
 | 
			
		||||
 | 
			
		||||
@@ -632,6 +634,7 @@ server_client_in_callback(
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	bufferevent_disable(c->stdin_event, EV_READ|EV_WRITE);
 | 
			
		||||
	setblocking(c->stdin_fd, 1);
 | 
			
		||||
	close(c->stdin_fd);
 | 
			
		||||
	c->stdin_fd = -1;
 | 
			
		||||
 | 
			
		||||
@@ -647,6 +650,7 @@ server_client_out_callback(
 | 
			
		||||
	struct client	*c = data;
 | 
			
		||||
 | 
			
		||||
	bufferevent_disable(c->stdout_event, EV_READ|EV_WRITE);
 | 
			
		||||
	setblocking(c->stdout_fd, 1);
 | 
			
		||||
	close(c->stdout_fd);
 | 
			
		||||
	c->stdout_fd = -1;
 | 
			
		||||
}
 | 
			
		||||
@@ -659,6 +663,7 @@ server_client_err_callback(
 | 
			
		||||
	struct client	*c = data;
 | 
			
		||||
 | 
			
		||||
	bufferevent_disable(c->stderr_event, EV_READ|EV_WRITE);
 | 
			
		||||
	setblocking(c->stderr_fd, 1);
 | 
			
		||||
	close(c->stderr_fd);
 | 
			
		||||
	c->stderr_fd = -1;
 | 
			
		||||
}
 | 
			
		||||
@@ -672,7 +677,6 @@ server_client_msg_dispatch(struct client *c)
 | 
			
		||||
	struct msg_identify_data identifydata;
 | 
			
		||||
	struct msg_environ_data	 environdata;
 | 
			
		||||
	ssize_t			 n, datalen;
 | 
			
		||||
	int			 mode;
 | 
			
		||||
 | 
			
		||||
	if ((n = imsg_read(&c->ibuf)) == -1 || n == 0)
 | 
			
		||||
		return (-1);
 | 
			
		||||
@@ -712,9 +716,7 @@ server_client_msg_dispatch(struct client *c)
 | 
			
		||||
			    NULL, NULL, server_client_in_callback, c);
 | 
			
		||||
			if (c->stdin_event == NULL)
 | 
			
		||||
				fatalx("failed to create stdin event");
 | 
			
		||||
 | 
			
		||||
			if ((mode = fcntl(c->stdin_fd, F_GETFL)) != -1)
 | 
			
		||||
				fcntl(c->stdin_fd, F_SETFL, mode|O_NONBLOCK);
 | 
			
		||||
			setblocking(c->stdin_fd, 0);
 | 
			
		||||
 | 
			
		||||
			server_client_msg_identify(c, &identifydata, imsg.fd);
 | 
			
		||||
			break;
 | 
			
		||||
@@ -729,9 +731,8 @@ server_client_msg_dispatch(struct client *c)
 | 
			
		||||
			    NULL, NULL, server_client_out_callback, c);
 | 
			
		||||
			if (c->stdout_event == NULL)
 | 
			
		||||
				fatalx("failed to create stdout event");
 | 
			
		||||
			setblocking(c->stdout_fd, 0);
 | 
			
		||||
 | 
			
		||||
			if ((mode = fcntl(c->stdout_fd, F_GETFL)) != -1)
 | 
			
		||||
				fcntl(c->stdout_fd, F_SETFL, mode|O_NONBLOCK);
 | 
			
		||||
			break;
 | 
			
		||||
		case MSG_STDERR:
 | 
			
		||||
			if (datalen != 0)
 | 
			
		||||
@@ -744,9 +745,8 @@ server_client_msg_dispatch(struct client *c)
 | 
			
		||||
			    NULL, NULL, server_client_err_callback, c);
 | 
			
		||||
			if (c->stderr_event == NULL)
 | 
			
		||||
				fatalx("failed to create stderr event");
 | 
			
		||||
			setblocking(c->stderr_fd, 0);
 | 
			
		||||
 | 
			
		||||
			if ((mode = fcntl(c->stderr_fd, F_GETFL)) != -1)
 | 
			
		||||
				fcntl(c->stderr_fd, F_SETFL, mode|O_NONBLOCK);
 | 
			
		||||
			break;
 | 
			
		||||
		case MSG_RESIZE:
 | 
			
		||||
			if (datalen != 0)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								server.c
									
									
									
									
									
								
							@@ -74,7 +74,7 @@ server_create_socket(void)
 | 
			
		||||
	struct sockaddr_un	sa;
 | 
			
		||||
	size_t			size;
 | 
			
		||||
	mode_t			mask;
 | 
			
		||||
	int			fd, mode;
 | 
			
		||||
	int			fd;
 | 
			
		||||
 | 
			
		||||
	memset(&sa, 0, sizeof sa);
 | 
			
		||||
	sa.sun_family = AF_UNIX;
 | 
			
		||||
@@ -95,11 +95,7 @@ server_create_socket(void)
 | 
			
		||||
 | 
			
		||||
	if (listen(fd, 16) == -1)
 | 
			
		||||
		fatal("listen failed");
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(fd, F_GETFL)) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	setblocking(fd, 0);
 | 
			
		||||
 | 
			
		||||
	server_update_socket();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								tmux.c
									
									
									
									
									
								
							@@ -194,12 +194,25 @@ makesocketpath(const char *label)
 | 
			
		||||
	return (path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
setblocking(int fd, int state)
 | 
			
		||||
{
 | 
			
		||||
	int mode;
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(fd, F_GETFL)) != -1) {
 | 
			
		||||
		if (!state)
 | 
			
		||||
			mode |= O_NONBLOCK;
 | 
			
		||||
		else
 | 
			
		||||
			mode &= ~O_NONBLOCK;
 | 
			
		||||
		fcntl(fd, F_SETFL, mode);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__dead void
 | 
			
		||||
shell_exec(const char *shell, const char *shellcmd)
 | 
			
		||||
{
 | 
			
		||||
	const char	*shellname, *ptr;
 | 
			
		||||
	char		*argv0;
 | 
			
		||||
	int		 mode;
 | 
			
		||||
 | 
			
		||||
	ptr = strrchr(shell, '/');
 | 
			
		||||
	if (ptr != NULL && *(ptr + 1) != '\0')
 | 
			
		||||
@@ -212,12 +225,9 @@ shell_exec(const char *shell, const char *shellcmd)
 | 
			
		||||
		xasprintf(&argv0, "%s", shellname);
 | 
			
		||||
	setenv("SHELL", shell, 1);
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(STDIN_FILENO, F_GETFL)) != -1)
 | 
			
		||||
		fcntl(STDIN_FILENO, F_SETFL, mode & ~O_NONBLOCK);
 | 
			
		||||
	if ((mode = fcntl(STDOUT_FILENO, F_GETFL)) != -1)
 | 
			
		||||
		fcntl(STDOUT_FILENO, F_SETFL, mode & ~O_NONBLOCK);
 | 
			
		||||
	if ((mode = fcntl(STDERR_FILENO, F_GETFL)) != -1)
 | 
			
		||||
		fcntl(STDERR_FILENO, F_SETFL, mode & ~O_NONBLOCK);
 | 
			
		||||
	setblocking(STDIN_FILENO, 1);
 | 
			
		||||
	setblocking(STDOUT_FILENO, 1);
 | 
			
		||||
	setblocking(STDERR_FILENO, 1);
 | 
			
		||||
	closefrom(STDERR_FILENO + 1);
 | 
			
		||||
 | 
			
		||||
	execl(shell, argv0, "-c", shellcmd, (char *) NULL);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1308,6 +1308,7 @@ void		 logfile(const char *);
 | 
			
		||||
const char	*getshell(void);
 | 
			
		||||
int		 checkshell(const char *);
 | 
			
		||||
int		 areshell(const char *);
 | 
			
		||||
void		 setblocking(int, int);
 | 
			
		||||
__dead void	 shell_exec(const char *, const char *);
 | 
			
		||||
 | 
			
		||||
/* cfg.c */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								tty.c
									
									
									
									
									
								
							@@ -165,15 +165,11 @@ void
 | 
			
		||||
tty_start_tty(struct tty *tty)
 | 
			
		||||
{
 | 
			
		||||
	struct termios	 tio;
 | 
			
		||||
	int		 mode;
 | 
			
		||||
 | 
			
		||||
	if (tty->fd == -1)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(tty->fd, F_GETFL)) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	if (fcntl(tty->fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	setblocking(tty->fd, 0);
 | 
			
		||||
 | 
			
		||||
	bufferevent_enable(tty->event, EV_READ|EV_WRITE);
 | 
			
		||||
 | 
			
		||||
@@ -220,7 +216,6 @@ void
 | 
			
		||||
tty_stop_tty(struct tty *tty)
 | 
			
		||||
{
 | 
			
		||||
	struct winsize	ws;
 | 
			
		||||
	int		mode;
 | 
			
		||||
 | 
			
		||||
	if (!(tty->flags & TTY_STARTED))
 | 
			
		||||
		return;
 | 
			
		||||
@@ -251,8 +246,7 @@ tty_stop_tty(struct tty *tty)
 | 
			
		||||
 | 
			
		||||
	tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP));
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(tty->fd, F_GETFL)) != -1)
 | 
			
		||||
		fcntl(tty->fd, F_SETFL, mode & ~O_NONBLOCK);
 | 
			
		||||
	setblocking(tty->fd, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								window.c
									
									
									
									
									
								
							@@ -563,7 +563,6 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
 | 
			
		||||
    const char *cwd, struct environ *env, struct termios *tio, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct winsize	 ws;
 | 
			
		||||
	int		 mode;
 | 
			
		||||
	char		*argv0;
 | 
			
		||||
	const char	*ptr;
 | 
			
		||||
	struct termios	 tio2;
 | 
			
		||||
@@ -637,10 +636,8 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
 | 
			
		||||
		fatal("execl failed");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(wp->fd, F_GETFL)) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	if (fcntl(wp->fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	setblocking(wp->fd, 0);
 | 
			
		||||
 | 
			
		||||
	wp->event = bufferevent_new(wp->fd,
 | 
			
		||||
	    window_pane_read_callback, NULL, window_pane_error_callback, wp);
 | 
			
		||||
	bufferevent_enable(wp->event, EV_READ|EV_WRITE);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user