mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Sync OpenBSD patchset 369:
Instead of passing a struct pollfd ** around through various functions, build them into a tree and then convert into a flat poll array before and after poll. This adds a little code but should reduce annoying problems with ordering when adding new things that also need to be polled.
This commit is contained in:
		
							
								
								
									
										220
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										220
									
								
								server.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: server.c,v 1.195 2009-10-06 14:00:50 tcunha Exp $ */
 | 
			
		||||
/* $Id: server.c,v 1.196 2009-10-11 23:25:44 tcunha Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -44,16 +44,33 @@
 | 
			
		||||
struct clients	 clients;
 | 
			
		||||
struct clients	 dead_clients;
 | 
			
		||||
 | 
			
		||||
/* Mapping of a pollfd to an fd independent of its position in the array. */
 | 
			
		||||
struct poll_item {
 | 
			
		||||
	struct pollfd	 pfd;
 | 
			
		||||
 | 
			
		||||
	RB_ENTRY(poll_item) entry;
 | 
			
		||||
};
 | 
			
		||||
RB_HEAD(poll_items, poll_item) poll_items;
 | 
			
		||||
 | 
			
		||||
int		 server_poll_cmp(struct poll_item *, struct poll_item *);
 | 
			
		||||
struct pollfd	*server_poll_lookup(int);
 | 
			
		||||
void		 server_poll_add(int, int);
 | 
			
		||||
struct pollfd	*server_poll_flatten(int *);
 | 
			
		||||
void		 server_poll_parse(struct pollfd *);
 | 
			
		||||
void		 server_poll_reset(void);
 | 
			
		||||
RB_PROTOTYPE(poll_items, poll_item, entry, server_poll_cmp);
 | 
			
		||||
RB_GENERATE(poll_items, poll_item, entry, server_poll_cmp);
 | 
			
		||||
 | 
			
		||||
void		 server_create_client(int);
 | 
			
		||||
int		 server_create_socket(void);
 | 
			
		||||
int		 server_main(int);
 | 
			
		||||
void		 server_shutdown(void);
 | 
			
		||||
int		 server_should_shutdown(void);
 | 
			
		||||
void		 server_child_signal(void);
 | 
			
		||||
void		 server_fill_windows(struct pollfd **);
 | 
			
		||||
void		 server_handle_windows(struct pollfd **);
 | 
			
		||||
void		 server_fill_clients(struct pollfd **);
 | 
			
		||||
void		 server_handle_clients(struct pollfd **);
 | 
			
		||||
void		 server_fill_windows(void);
 | 
			
		||||
void		 server_handle_windows(void);
 | 
			
		||||
void		 server_fill_clients(void);
 | 
			
		||||
void		 server_handle_clients(void);
 | 
			
		||||
void		 server_accept_client(int);
 | 
			
		||||
void		 server_handle_client(struct client *);
 | 
			
		||||
void		 server_handle_window(struct window *, struct window_pane *);
 | 
			
		||||
@@ -71,6 +88,75 @@ void		 server_check_timers(struct client *);
 | 
			
		||||
void		 server_second_timers(void);
 | 
			
		||||
int		 server_update_socket(void);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
server_poll_cmp(struct poll_item *pitem1, struct poll_item *pitem2)
 | 
			
		||||
{
 | 
			
		||||
	return (pitem1->pfd.fd - pitem2->pfd.fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pollfd *
 | 
			
		||||
server_poll_lookup(int fd)
 | 
			
		||||
{
 | 
			
		||||
	struct poll_item	pitem;
 | 
			
		||||
 | 
			
		||||
	pitem.pfd.fd = fd;
 | 
			
		||||
	return (&RB_FIND(poll_items, &poll_items, &pitem)->pfd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
server_poll_add(int fd, int events)
 | 
			
		||||
{
 | 
			
		||||
	struct poll_item	*pitem;
 | 
			
		||||
 | 
			
		||||
	pitem = xmalloc(sizeof *pitem);
 | 
			
		||||
	pitem->pfd.fd = fd;
 | 
			
		||||
	pitem->pfd.events = events;
 | 
			
		||||
	RB_INSERT(poll_items, &poll_items, pitem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pollfd *
 | 
			
		||||
server_poll_flatten(int *nfds)
 | 
			
		||||
{
 | 
			
		||||
	struct poll_item	*pitem;
 | 
			
		||||
	struct pollfd		*pfds;
 | 
			
		||||
 | 
			
		||||
	pfds = NULL;
 | 
			
		||||
	*nfds = 0;
 | 
			
		||||
	RB_FOREACH(pitem, poll_items, &poll_items) {
 | 
			
		||||
		pfds = xrealloc(pfds, (*nfds) + 1, sizeof *pfds);
 | 
			
		||||
		pfds[*nfds].fd = pitem->pfd.fd;
 | 
			
		||||
		pfds[*nfds].events = pitem->pfd.events;
 | 
			
		||||
		(*nfds)++;
 | 
			
		||||
	}
 | 
			
		||||
	return (pfds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
server_poll_parse(struct pollfd *pfds)
 | 
			
		||||
{
 | 
			
		||||
	struct poll_item	*pitem;
 | 
			
		||||
	int			 nfds;
 | 
			
		||||
 | 
			
		||||
	nfds = 0;
 | 
			
		||||
	RB_FOREACH(pitem, poll_items, &poll_items) {
 | 
			
		||||
		pitem->pfd.revents = pfds[nfds].revents;
 | 
			
		||||
		nfds++;
 | 
			
		||||
	}
 | 
			
		||||
	xfree(pfds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
server_poll_reset(void)
 | 
			
		||||
{
 | 
			
		||||
	struct poll_item	*pitem;
 | 
			
		||||
 | 
			
		||||
	while (!RB_EMPTY(&poll_items)) {
 | 
			
		||||
		pitem = RB_ROOT(&poll_items);
 | 
			
		||||
		RB_REMOVE(poll_items, &poll_items, pitem);
 | 
			
		||||
		xfree(pitem);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Create a new client. */
 | 
			
		||||
void
 | 
			
		||||
server_create_client(int fd)
 | 
			
		||||
@@ -248,7 +334,6 @@ server_create_socket(void)
 | 
			
		||||
int
 | 
			
		||||
server_main(int srv_fd)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
	struct pollfd	*pfds, *pfd;
 | 
			
		||||
	int		 nfds, xtimeout;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
@@ -282,26 +367,13 @@ server_main(int srv_fd)
 | 
			
		||||
			sigusr1 = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Initialise pollfd array. */
 | 
			
		||||
		nfds = 1;
 | 
			
		||||
		for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
 | 
			
		||||
			w = ARRAY_ITEM(&windows, i);
 | 
			
		||||
			if (w != NULL)
 | 
			
		||||
				nfds += window_count_panes(w);
 | 
			
		||||
		}
 | 
			
		||||
		nfds += ARRAY_LENGTH(&clients) * 2;
 | 
			
		||||
		pfds = xrealloc(pfds, nfds, sizeof *pfds);
 | 
			
		||||
		memset(pfds, 0, nfds * sizeof *pfds);
 | 
			
		||||
		pfd = pfds;
 | 
			
		||||
 | 
			
		||||
		/* Fill server socket. */
 | 
			
		||||
		pfd->fd = srv_fd;
 | 
			
		||||
		pfd->events = POLLIN;
 | 
			
		||||
		pfd++;
 | 
			
		||||
		/* Initialise pollfd array and add server socket. */
 | 
			
		||||
		server_poll_reset();
 | 
			
		||||
		server_poll_add(srv_fd, POLLIN);
 | 
			
		||||
 | 
			
		||||
		/* Fill window and client sockets. */
 | 
			
		||||
		server_fill_windows(&pfd);
 | 
			
		||||
		server_fill_clients(&pfd);
 | 
			
		||||
		server_fill_windows();
 | 
			
		||||
		server_fill_clients();
 | 
			
		||||
 | 
			
		||||
		/* Update socket permissions. */
 | 
			
		||||
		xtimeout = INFTIM;
 | 
			
		||||
@@ -309,21 +381,23 @@ server_main(int srv_fd)
 | 
			
		||||
			xtimeout = POLL_TIMEOUT;
 | 
			
		||||
 | 
			
		||||
		/* Do the poll. */
 | 
			
		||||
		pfds = server_poll_flatten(&nfds);
 | 
			
		||||
		log_debug("polling %d", nfds);
 | 
			
		||||
		if (poll(pfds, nfds, xtimeout) == -1) {
 | 
			
		||||
			if (errno == EAGAIN || errno == EINTR)
 | 
			
		||||
				continue;
 | 
			
		||||
			fatal("poll failed");
 | 
			
		||||
		}
 | 
			
		||||
		pfd = pfds;
 | 
			
		||||
		server_poll_parse(pfds);
 | 
			
		||||
 | 
			
		||||
		/* Handle server socket. */
 | 
			
		||||
		pfd = server_poll_lookup(srv_fd);
 | 
			
		||||
		if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
 | 
			
		||||
			fatalx("lost server socket");
 | 
			
		||||
		if (pfd->revents & POLLIN) {
 | 
			
		||||
			server_accept_client(srv_fd);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		pfd++;
 | 
			
		||||
 | 
			
		||||
		/* Call second-based timers. */
 | 
			
		||||
		now = time(NULL);
 | 
			
		||||
@@ -340,8 +414,8 @@ server_main(int srv_fd)
 | 
			
		||||
		 * windows, so windows must come first to avoid messing up by
 | 
			
		||||
		 * increasing the array size.
 | 
			
		||||
		 */
 | 
			
		||||
		server_handle_windows(&pfd);
 | 
			
		||||
		server_handle_clients(&pfd);
 | 
			
		||||
		server_handle_windows();
 | 
			
		||||
		server_handle_clients();
 | 
			
		||||
 | 
			
		||||
		/* Collect any unset key bindings. */
 | 
			
		||||
		key_bindings_clean();
 | 
			
		||||
@@ -349,8 +423,7 @@ server_main(int srv_fd)
 | 
			
		||||
		/* Collect dead clients and sessions. */
 | 
			
		||||
		server_clean_dead();
 | 
			
		||||
	}
 | 
			
		||||
	if (pfds != NULL)
 | 
			
		||||
		xfree(pfds);
 | 
			
		||||
	server_poll_reset();
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
			
		||||
		if (ARRAY_ITEM(&sessions, i) != NULL)
 | 
			
		||||
@@ -467,35 +540,36 @@ server_child_signal(void)
 | 
			
		||||
 | 
			
		||||
/* Fill window pollfds. */
 | 
			
		||||
void
 | 
			
		||||
server_fill_windows(struct pollfd **pfd)
 | 
			
		||||
server_fill_windows(void)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int		 	 i;
 | 
			
		||||
	int			 events;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
 | 
			
		||||
		w = ARRAY_ITEM(&windows, i);
 | 
			
		||||
		if (w == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
			(*pfd)->fd = wp->fd;
 | 
			
		||||
			if (wp->fd != -1) {
 | 
			
		||||
				(*pfd)->events = POLLIN;
 | 
			
		||||
				if (BUFFER_USED(wp->out) > 0)
 | 
			
		||||
					(*pfd)->events |= POLLOUT;
 | 
			
		||||
			}
 | 
			
		||||
			(*pfd)++;
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {	
 | 
			
		||||
			if (wp->fd == -1)
 | 
			
		||||
				continue;
 | 
			
		||||
			events = POLLIN;
 | 
			
		||||
			if (BUFFER_USED(wp->out) > 0)
 | 
			
		||||
				events |= POLLOUT;
 | 
			
		||||
			server_poll_add(wp->fd, events);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle window pollfds. */
 | 
			
		||||
void
 | 
			
		||||
server_handle_windows(struct pollfd **pfd)
 | 
			
		||||
server_handle_windows(void)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	struct pollfd		*pfd;
 | 
			
		||||
	u_int		 	 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
 | 
			
		||||
@@ -504,14 +578,15 @@ server_handle_windows(struct pollfd **pfd)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
			if (wp->fd != -1) {
 | 
			
		||||
				if (buffer_poll(*pfd, wp->in, wp->out) != 0) {
 | 
			
		||||
					close(wp->fd);
 | 
			
		||||
					wp->fd = -1;
 | 
			
		||||
				} else
 | 
			
		||||
					server_handle_window(w, wp);
 | 
			
		||||
			}
 | 
			
		||||
			(*pfd)++;
 | 
			
		||||
			if (wp->fd == -1)
 | 
			
		||||
				continue;
 | 
			
		||||
			if ((pfd = server_poll_lookup(wp->fd)) == NULL)
 | 
			
		||||
				continue;
 | 
			
		||||
			if (buffer_poll(pfd, wp->in, wp->out) != 0) {
 | 
			
		||||
				close(wp->fd);
 | 
			
		||||
				wp->fd = -1;
 | 
			
		||||
			} else
 | 
			
		||||
				server_handle_window(w, wp);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		server_check_window(w);
 | 
			
		||||
@@ -627,12 +702,13 @@ server_check_timers(struct client *c)
 | 
			
		||||
 | 
			
		||||
/* Fill client pollfds. */
 | 
			
		||||
void
 | 
			
		||||
server_fill_clients(struct pollfd **pfd)
 | 
			
		||||
server_fill_clients(void)
 | 
			
		||||
{
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int		 	 i;
 | 
			
		||||
	int			 events;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
@@ -640,27 +716,22 @@ server_fill_clients(struct pollfd **pfd)
 | 
			
		||||
		server_check_timers(c);
 | 
			
		||||
		server_check_redraw(c);
 | 
			
		||||
 | 
			
		||||
		if (c == NULL)
 | 
			
		||||
			(*pfd)->fd = -1;
 | 
			
		||||
		else {
 | 
			
		||||
			(*pfd)->fd = c->ibuf.fd;
 | 
			
		||||
		if (c != NULL) {
 | 
			
		||||
			events = 0;
 | 
			
		||||
			if (!(c->flags & CLIENT_BAD))
 | 
			
		||||
				(*pfd)->events |= POLLIN;
 | 
			
		||||
				events |= POLLIN;
 | 
			
		||||
			if (c->ibuf.w.queued > 0)
 | 
			
		||||
				(*pfd)->events |= POLLOUT;
 | 
			
		||||
				events |= POLLOUT;
 | 
			
		||||
			server_poll_add(c->ibuf.fd, events);
 | 
			
		||||
		}
 | 
			
		||||
		(*pfd)++;
 | 
			
		||||
 | 
			
		||||
		if (c == NULL || c->flags & CLIENT_SUSPENDED ||
 | 
			
		||||
		    c->tty.fd == -1 || c->session == NULL)
 | 
			
		||||
			(*pfd)->fd = -1;
 | 
			
		||||
		else {
 | 
			
		||||
			(*pfd)->fd = c->tty.fd;
 | 
			
		||||
			(*pfd)->events = POLLIN;
 | 
			
		||||
		if (c != NULL && !(c->flags & CLIENT_SUSPENDED) &&
 | 
			
		||||
		    c->tty.fd != -1 && c->session != NULL) {
 | 
			
		||||
			events = POLLIN;
 | 
			
		||||
			if (BUFFER_USED(c->tty.out) > 0)
 | 
			
		||||
				(*pfd)->events |= POLLOUT;
 | 
			
		||||
				events |= POLLOUT;
 | 
			
		||||
			server_poll_add(c->tty.fd, events);
 | 
			
		||||
		}
 | 
			
		||||
		(*pfd)++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -680,25 +751,26 @@ server_fill_clients(struct pollfd **pfd)
 | 
			
		||||
 | 
			
		||||
/* Handle client pollfds. */
 | 
			
		||||
void
 | 
			
		||||
server_handle_clients(struct pollfd **pfd)
 | 
			
		||||
server_handle_clients(void)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct pollfd	*pfd;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
 | 
			
		||||
		if (c != NULL) {
 | 
			
		||||
			if ((*pfd)->revents & (POLLERR|POLLNVAL|POLLHUP)) {
 | 
			
		||||
			if ((pfd = server_poll_lookup(c->ibuf.fd)) == NULL)
 | 
			
		||||
				continue;
 | 
			
		||||
			if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP)) {
 | 
			
		||||
				server_lost_client(c);
 | 
			
		||||
				(*pfd) += 2;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if ((*pfd)->revents & POLLOUT) {
 | 
			
		||||
			if (pfd->revents & POLLOUT) {
 | 
			
		||||
				if (msgbuf_write(&c->ibuf.w) < 0) {
 | 
			
		||||
					server_lost_client(c);
 | 
			
		||||
					(*pfd) += 2;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@@ -706,26 +778,24 @@ server_handle_clients(struct pollfd **pfd)
 | 
			
		||||
			if (c->flags & CLIENT_BAD) {
 | 
			
		||||
				if (c->ibuf.w.queued == 0)
 | 
			
		||||
					server_lost_client(c);
 | 
			
		||||
				(*pfd) += 2;
 | 
			
		||||
				continue;
 | 
			
		||||
			} else if ((*pfd)->revents & POLLIN) {
 | 
			
		||||
			} else if (pfd->revents & POLLIN) {
 | 
			
		||||
				if (server_msg_dispatch(c) != 0) {
 | 
			
		||||
					server_lost_client(c);
 | 
			
		||||
					(*pfd) += 2;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		(*pfd)++;
 | 
			
		||||
 | 
			
		||||
		if (c != NULL && !(c->flags & CLIENT_SUSPENDED) &&
 | 
			
		||||
		    c->tty.fd != -1 && c->session != NULL) {
 | 
			
		||||
			if (buffer_poll(*pfd, c->tty.in, c->tty.out) != 0)
 | 
			
		||||
			if ((pfd = server_poll_lookup(c->tty.fd)) == NULL)
 | 
			
		||||
				continue;
 | 
			
		||||
			if (buffer_poll(pfd, c->tty.in, c->tty.out) != 0)
 | 
			
		||||
				server_lost_client(c);
 | 
			
		||||
			else
 | 
			
		||||
				server_handle_client(c);
 | 
			
		||||
		}
 | 
			
		||||
		(*pfd)++;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user