summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicm <nicm>2015-06-05 18:01:12 +0000
committernicm <nicm>2015-06-05 18:01:12 +0000
commit8c93b768e4864be330c3d6a7962892135224f0f4 (patch)
tree783a393e81cd604e69a4b4aaabbc6acafb6410d6
parentb0782df8a64f744b7c067e6f918ce5217ea09e57 (diff)
Instead of putting dead clients on a list and checking it every loop,
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.
-rw-r--r--cmd-confirm-before.c2
-rw-r--r--cmd-load-buffer.c2
-rw-r--r--server-client.c37
-rw-r--r--server.c11
-rw-r--r--tmux.h1
5 files changed, 37 insertions, 16 deletions
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index 5e4816ed..e6104574 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -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);
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c
index 3a26db39..8f653929 100644
--- a/cmd-load-buffer.c
+++ b/cmd-load-buffer.c
@@ -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;
diff --git a/server-client.c b/server-client.c
index 01c8b313..b10c1e13 100644
--- a/server-client.c
+++ b/server-client.c
@@ -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)
diff --git a/server.c b/server.c
index 52fdb0c3..cc5a63f6 100644
--- a/server.c
+++ b/server.c
@@ -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. */
diff --git a/tmux.h b/tmux.h
index 8406955b..fa36fe6f 100644
--- a/tmux.h
+++ b/tmux.h
@@ -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);