Instead of putting dead clients on a list and checking it every loop,
authornicm <nicm@openbsd.org>
Fri, 5 Jun 2015 18:01:12 +0000 (18:01 +0000)
committernicm <nicm@openbsd.org>
Fri, 5 Jun 2015 18:01:12 +0000 (18:01 +0000)
use event_once to queue a callback to deal with them. Also dead clients
with references would never actually be freed because the wrap-up
functions (the callback for stdin, or status_prompt_clear) would never
be called. So call them in server_client_lost.

usr.bin/tmux/cmd-confirm-before.c
usr.bin/tmux/cmd-load-buffer.c
usr.bin/tmux/server-client.c
usr.bin/tmux/server.c
usr.bin/tmux/tmux.h

index 4a53398..5d29087 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-confirm-before.c,v 1.23 2015/04/19 21:34:21 nicm Exp $ */
+/* $OpenBSD: cmd-confirm-before.c,v 1.24 2015/06/05 18:01:12 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -117,7 +117,7 @@ cmd_confirm_before_free(void *data)
        struct cmd_confirm_before_data  *cdata = data;
        struct client                   *c = cdata->client;
 
-       c->references--;
+       server_client_deref(c);
 
        free(cdata->cmd);
        free(cdata);
index 161c554..da0846c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-load-buffer.c,v 1.32 2015/04/27 16:25:57 nicm Exp $ */
+/* $OpenBSD: cmd-load-buffer.c,v 1.33 2015/06/05 18:01:12 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -132,7 +132,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
                return;
        c->stdin_callback = NULL;
 
-       c->references--;
+       server_client_deref(c);
        if (c->flags & CLIENT_DEAD)
                return;
 
index e551c41..c9232bd 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.140 2015/06/04 23:27:51 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.141 2015/06/05 18:01:12 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,6 +31,7 @@
 #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,7 +86,7 @@ server_client_create(int fd)
        setblocking(fd, 0);
 
        c = xcalloc(1, sizeof *c);
-       c->references = 0;
+       c->references = 1;
        imsg_init(&c->ibuf, fd);
        server_update_event(c);
 
@@ -161,6 +162,14 @@ server_client_lost(struct client *c)
 {
        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,8 +222,7 @@ server_client_lost(struct client *c)
        if (event_initialized(&c->event))
                event_del(&c->event);
 
-       TAILQ_INSERT_TAIL(&dead_clients, c, entry);
-       c->flags |= CLIENT_DEAD;
+       server_client_deref(c);
 
        server_add_accept(0); /* may be more file descriptors now */
 
@@ -223,6 +231,29 @@ server_client_lost(struct client *c)
        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. */
 void
 server_client_callback(int fd, short events, void *data)
index 98cecda..4f157fd 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.126 2015/06/04 11:43:51 nicm Exp $ */
+/* $OpenBSD: server.c,v 1.127 2015/06/05 18:01:12 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -41,9 +41,7 @@
  * Main server functions.
  */
 
-/* Client list. */
 struct clients  clients;
-struct clients  dead_clients;
 
 int             server_fd;
 int             server_shutdown;
@@ -205,7 +203,6 @@ server_start(int lockfd, char *lockfile)
        RB_INIT(&windows);
        RB_INIT(&all_window_panes);
        TAILQ_INIT(&clients);
-       TAILQ_INIT(&dead_clients);
        RB_INIT(&sessions);
        RB_INIT(&dead_sessions);
        TAILQ_INIT(&session_groups);
@@ -325,7 +322,6 @@ void
 server_clean_dead(void)
 {
        struct session  *s, *s1;
-       struct client   *c, *c1;
 
        RB_FOREACH_SAFE(s, sessions, &dead_sessions, s1) {
                if (s->references != 0)
@@ -334,13 +330,6 @@ server_clean_dead(void)
                free(s->name);
                free(s);
        }
-
-       TAILQ_FOREACH_SAFE(c, &dead_clients, entry, c1) {
-               if (c->references != 0)
-                       continue;
-               TAILQ_REMOVE(&dead_clients, c, entry);
-               free(c);
-       }
 }
 
 /* Update socket execute permissions based on whether sessions are attached. */
index 2af070f..148c2dd 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.517 2015/06/04 23:27:51 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.518 2015/06/05 18:01:12 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -1871,6 +1871,7 @@ int        server_client_check_nested(struct client *);
 void    server_client_handle_key(struct client *, int);
 void    server_client_create(int);
 int     server_client_open(struct client *, char **);
+void    server_client_deref(struct client *);
 void    server_client_lost(struct client *);
 void    server_client_callback(int, short, void *);
 void    server_client_status_timer(void);