=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/server.c,v retrieving revision 1.30 retrieving revision 1.31 diff -c -r1.30 -r1.31 *** src/usr.bin/tmux/server.c 2009/09/07 19:08:45 1.30 --- src/usr.bin/tmux/server.c 2009/09/07 21:01:50 1.31 *************** *** 1,4 **** ! /* $OpenBSD: server.c,v 1.30 2009/09/07 19:08:45 kili Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: server.c,v 1.31 2009/09/07 21:01:50 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott *************** *** 43,48 **** --- 43,49 ---- /* Client list. */ struct clients clients; + struct clients dead_clients; void server_create_client(int); int server_create_socket(void); *************** *** 61,66 **** --- 62,68 ---- struct window *); int server_check_window_content(struct session *, struct window *, struct window_pane *); + void server_clean_dead(void); void server_lost_client(struct client *); void server_check_window(struct window *); void server_check_redraw(struct client *); *************** *** 85,90 **** --- 87,93 ---- fatal("fcntl failed"); c = xcalloc(1, sizeof *c); + c->references = 0; imsg_init(&c->ibuf, fd); ARRAY_INIT(&c->prompt_hdata); *************** *** 162,168 **** --- 165,173 ---- ARRAY_INIT(&windows); ARRAY_INIT(&clients); + ARRAY_INIT(&dead_clients); ARRAY_INIT(&sessions); + ARRAY_INIT(&dead_sessions); mode_key_init_trees(); key_bindings_init(); utf8_build(); *************** *** 344,349 **** --- 349,357 ---- /* Collect any unset key bindings. */ key_bindings_clean(); + + /* Collect dead clients and sessions. */ + server_clean_dead(); /* * If we have no sessions and clients left, let's get out *************** *** 948,956 **** close(c->ibuf.fd); imsg_clear(&c->ibuf); - xfree(c); recalculate_sizes(); } /* Handle window data. */ --- 956,998 ---- close(c->ibuf.fd); imsg_clear(&c->ibuf); + for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) { + if (ARRAY_ITEM(&dead_clients, i) == NULL) { + ARRAY_SET(&dead_clients, i, c); + break; + } + } + if (i == ARRAY_LENGTH(&dead_clients)) + ARRAY_ADD(&dead_clients, c); + c->flags |= CLIENT_DEAD; + recalculate_sizes(); + } + + /* Free dead, unreferenced clients and sessions. */ + void + server_clean_dead(void) + { + struct session *s; + struct client *c; + u_int i; + + for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) { + s = ARRAY_ITEM(&dead_sessions, i); + if (s == NULL || s->references != 0) + continue; + ARRAY_SET(&dead_sessions, i, NULL); + xfree(s); + } + + for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) { + c = ARRAY_ITEM(&dead_clients, i); + if (c == NULL || c->references != 0) + continue; + ARRAY_SET(&dead_clients, i, NULL); + xfree(c); + } } /* Handle window data. */