=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/server.c,v retrieving revision 1.44 retrieving revision 1.45 diff -c -r1.44 -r1.45 *** src/usr.bin/tmux/server.c 2009/10/05 18:30:54 1.44 --- src/usr.bin/tmux/server.c 2009/10/10 09:31:39 1.45 *************** *** 1,4 **** ! /* $OpenBSD: server.c,v 1.44 2009/10/05 18:30:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: server.c,v 1.45 2009/10/10 09:31:39 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott *************** *** 45,60 **** struct clients clients; struct clients dead_clients; 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_accept_client(int); void server_handle_client(struct client *); void server_handle_window(struct window *, struct window_pane *); --- 45,77 ---- 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(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 *); *************** *** 72,77 **** --- 89,163 ---- 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) *************** *** 245,251 **** int server_main(int srv_fd) { - struct window *w; struct pollfd *pfds, *pfd; int nfds, xtimeout; u_int i; --- 331,336 ---- *************** *** 279,304 **** 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++; - /* Fill window and client sockets. */ ! server_fill_windows(&pfd); ! server_fill_clients(&pfd); /* Update socket permissions. */ xtimeout = INFTIM; --- 364,376 ---- sigusr1 = 0; } ! /* Initialise pollfd array and add server socket. */ ! server_poll_reset(); ! server_poll_add(srv_fd, POLLIN); /* Fill window and client sockets. */ ! server_fill_windows(); ! server_fill_clients(); /* Update socket permissions. */ xtimeout = INFTIM; *************** *** 306,326 **** xtimeout = POLL_TIMEOUT; /* Do the poll. */ if (poll(pfds, nfds, xtimeout) == -1) { if (errno == EAGAIN || errno == EINTR) continue; fatal("poll failed"); } ! pfd = pfds; /* Handle server socket. */ 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); --- 378,400 ---- 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"); } ! 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; } /* Call second-based timers. */ now = time(NULL); *************** *** 337,344 **** * windows, so windows must come first to avoid messing up by * increasing the array size. */ ! server_handle_windows(&pfd); ! server_handle_clients(&pfd); /* Collect any unset key bindings. */ key_bindings_clean(); --- 411,418 ---- * windows, so windows must come first to avoid messing up by * increasing the array size. */ ! server_handle_windows(); ! server_handle_clients(); /* Collect any unset key bindings. */ key_bindings_clean(); *************** *** 346,353 **** /* Collect dead clients and sessions. */ server_clean_dead(); } ! if (pfds != NULL) ! xfree(pfds); for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { if (ARRAY_ITEM(&sessions, i) != NULL) --- 420,426 ---- /* Collect dead clients and sessions. */ server_clean_dead(); } ! server_poll_reset(); for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { if (ARRAY_ITEM(&sessions, i) != NULL) *************** *** 464,498 **** /* Fill window pollfds. */ void ! server_fill_windows(struct pollfd **pfd) { struct window *w; struct window_pane *wp; u_int i; 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)++; } } } /* Handle window pollfds. */ void ! server_handle_windows(struct pollfd **pfd) { struct window *w; struct window_pane *wp; u_int i; for (i = 0; i < ARRAY_LENGTH(&windows); i++) { --- 537,572 ---- /* Fill window pollfds. */ void ! 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) { ! 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(void) { struct window *w; struct window_pane *wp; + struct pollfd *pfd; u_int i; for (i = 0; i < ARRAY_LENGTH(&windows); i++) { *************** *** 501,514 **** 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)++; } server_check_window(w); --- 575,589 ---- continue; TAILQ_FOREACH(wp, &w->panes, entry) { ! 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); *************** *** 624,635 **** /* Fill client pollfds. */ void ! server_fill_clients(struct pollfd **pfd) { struct client *c; struct window *w; struct window_pane *wp; u_int i; for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); --- 699,711 ---- /* Fill client pollfds. */ void ! 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); *************** *** 637,663 **** server_check_timers(c); server_check_redraw(c); ! if (c == NULL) ! (*pfd)->fd = -1; ! else { ! (*pfd)->fd = c->ibuf.fd; if (!(c->flags & CLIENT_BAD)) ! (*pfd)->events |= POLLIN; if (c->ibuf.w.queued > 0) ! (*pfd)->events |= POLLOUT; } - (*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 (BUFFER_USED(c->tty.out) > 0) ! (*pfd)->events |= POLLOUT; } - (*pfd)++; } /* --- 713,734 ---- server_check_timers(c); server_check_redraw(c); ! if (c != NULL) { ! events = 0; if (!(c->flags & CLIENT_BAD)) ! events |= POLLIN; if (c->ibuf.w.queued > 0) ! events |= POLLOUT; ! server_poll_add(c->ibuf.fd, events); } ! if (c != NULL && !(c->flags & CLIENT_SUSPENDED) && ! c->tty.fd != -1 && c->session != NULL) { ! events = POLLIN; if (BUFFER_USED(c->tty.out) > 0) ! events |= POLLOUT; ! server_poll_add(c->tty.fd, events); } } /* *************** *** 677,701 **** /* Handle client pollfds. */ void ! server_handle_clients(struct pollfd **pfd) { struct client *c; 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)) { server_lost_client(c); - (*pfd) += 2; continue; } ! if ((*pfd)->revents & POLLOUT) { if (msgbuf_write(&c->ibuf.w) < 0) { server_lost_client(c); - (*pfd) += 2; continue; } } --- 748,773 ---- /* Handle client pollfds. */ void ! 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 = server_poll_lookup(c->ibuf.fd)) == NULL) ! continue; ! if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP)) { server_lost_client(c); continue; } ! if (pfd->revents & POLLOUT) { if (msgbuf_write(&c->ibuf.w) < 0) { server_lost_client(c); continue; } } *************** *** 703,728 **** if (c->flags & CLIENT_BAD) { if (c->ibuf.w.queued == 0) server_lost_client(c); - (*pfd) += 2; continue; ! } 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) server_lost_client(c); else server_handle_client(c); } - (*pfd)++; } } --- 775,798 ---- if (c->flags & CLIENT_BAD) { if (c->ibuf.w.queued == 0) server_lost_client(c); continue; ! } else if (pfd->revents & POLLIN) { if (server_msg_dispatch(c) != 0) { server_lost_client(c); continue; } } } if (c != NULL && !(c->flags & CLIENT_SUSPENDED) && c->tty.fd != -1 && c->session != NULL) { ! 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); } } }