=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/server-client.c,v retrieving revision 1.140 retrieving revision 1.141 diff -c -r1.140 -r1.141 *** src/usr.bin/tmux/server-client.c 2015/06/04 23:27:51 1.140 --- src/usr.bin/tmux/server-client.c 2015/06/05 18:01:12 1.141 *************** *** 1,4 **** ! /* $OpenBSD: server-client.c,v 1.140 2015/06/04 23:27:51 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: server-client.c,v 1.141 2015/06/05 18:01:12 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott *************** *** 31,36 **** --- 31,37 ---- #include "tmux.h" void server_client_key_table(struct client *, const char *); + void server_client_free(int, short, void *); void server_client_check_focus(struct window_pane *); void server_client_check_resize(struct window_pane *); int server_client_check_mouse(struct client *); *************** *** 85,91 **** setblocking(fd, 0); c = xcalloc(1, sizeof *c); ! c->references = 0; imsg_init(&c->ibuf, fd); server_update_event(c); --- 86,92 ---- setblocking(fd, 0); c = xcalloc(1, sizeof *c); ! c->references = 1; imsg_init(&c->ibuf, fd); server_update_event(c); *************** *** 161,166 **** --- 162,175 ---- { struct message_entry *msg, *msg1; + c->flags |= CLIENT_DEAD; + + status_prompt_clear(c); + status_message_clear(c); + + if (c->stdin_callback != NULL) + c->stdin_callback(c, 1, c->stdin_callback_data); + TAILQ_REMOVE(&clients, c, entry); log_debug("lost client %d", c->ibuf.fd); *************** *** 213,226 **** if (event_initialized(&c->event)) event_del(&c->event); ! TAILQ_INSERT_TAIL(&dead_clients, c, entry); ! c->flags |= CLIENT_DEAD; server_add_accept(0); /* may be more file descriptors now */ recalculate_sizes(); server_check_unattached(); server_update_socket(); } /* Process a single client event. */ --- 222,257 ---- if (event_initialized(&c->event)) event_del(&c->event); ! server_client_deref(c); server_add_accept(0); /* may be more file descriptors now */ recalculate_sizes(); server_check_unattached(); server_update_socket(); + } + + /* Remove reference from a client. */ + void + server_client_deref(struct client *c) + { + log_debug("deref client %d (%d references)", c->ibuf.fd, c->references); + + c->references--; + if (c->references == 0) + event_once(-1, EV_TIMEOUT, server_client_free, c, NULL); + } + + /* Free dead client. */ + void + server_client_free(unused int fd, unused short events, void *arg) + { + struct client *c = arg; + + log_debug("free client %d (%d references)", c->ibuf.fd, c->references); + + if (c->references == 0) + free(c); } /* Process a single client event. */