mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	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.
This commit is contained in:
		@@ -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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user