[Xcb] [PATCH 1/2 v2] xcb_disconnect(): Fix leak with error connections

Uli Schlachter psychon at znc.in
Wed Feb 19 12:33:11 PST 2014

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);
    xcb_discard_reply(c, xcb_get_input_focus(c).sequence);

Valgrind confirms that xcb has a memory leak before this patch that this patch
indeed fixes.

Signed-off-by: Uli Schlachter <psychon at znc.in>
 src/xcb_conn.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 46390e1..528afab 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))

More information about the Xcb mailing list