summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUli Schlachter <psychon@znc.in>2013-12-31 15:05:36 +0100
committerUli Schlachter <psychon@znc.in>2014-03-21 14:38:58 +0100
commit4dcbfd77b78ca6b016ce815af26235501f6cd75a (patch)
tree3c848875f27c3f98df05b31b2e6cc27d3996e1b2
parentd84dd752ef571491b015443fefedca53c7f81282 (diff)
xcb_disconnect(): Fix leak with error connections
There are two kind of error connections in XCB. First, if something goes wrong while the connection is being set up, _xcb_conn_ret_error() is used to return a static connection in an error state. If something goes wrong later, _xcb_conn_shutdown() is used to set c->has_error. This is important, because the static object that _xcb_conn_ret_error() returns must not be freed, while the dynamically allocated objects that go through _xcb_conn_shutdown() must obviously be properly deallocated. This used to work correctly, but in 769acff0da8, xcb_disconnect() was made to ignore all connections in an error state completely. Fix this by only ignoring the few static error connections that we have. This was tested with the following hack: xcb_connection_t *c = xcb_connect(NULL, NULL); close(xcb_get_file_descriptor(c)); xcb_discard_reply(c, xcb_get_input_focus(c).sequence); xcb_flush(c); xcb_disconnect(c); Valgrind confirms that xcb has a memory leak before this patch that this patch indeed fixes. Signed-off-by: Uli Schlachter <psychon@znc.in> Reviewed-by: Julien Cristau <jcristau@debian.org>
-rw-r--r--src/xcb_conn.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index ae51b93..ab901a9 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -64,11 +64,20 @@ typedef struct {
uint16_t length;
} xcb_setup_generic_t;
+/* Keep this list in sync with is_static_error_conn()! */
static const int xcb_con_error = XCB_CONN_ERROR;
static const int xcb_con_closed_mem_er = XCB_CONN_CLOSED_MEM_INSUFFICIENT;
static const int xcb_con_closed_parse_er = XCB_CONN_CLOSED_PARSE_ERR;
static const int xcb_con_closed_screen_er = XCB_CONN_CLOSED_INVALID_SCREEN;
+static int is_static_error_conn(xcb_connection_t *c)
+{
+ return c == (xcb_connection_t *) &xcb_con_error ||
+ c == (xcb_connection_t *) &xcb_con_closed_mem_er ||
+ c == (xcb_connection_t *) &xcb_con_closed_parse_er ||
+ c == (xcb_connection_t *) &xcb_con_closed_screen_er;
+}
+
static int set_fd_flags(const int fd)
{
/* Win32 doesn't have file descriptors and the fcntl function. This block sets the socket in non-blocking mode */
@@ -341,7 +350,7 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
void xcb_disconnect(xcb_connection_t *c)
{
- if(c->has_error)
+ if(is_static_error_conn(c))
return;
free(c->setup);