Search code examples
crecursionxorgwindow-managersxcb

Weird recursive behavior using XCB


I'm exploring creating a window manager using XCB, but I've run into some troubles pretty early on. My code won't even connect to XCB with xcb_connect. I thought it was pretty straightforward, but I'm getting some really strange behavior. My code looks like this:

#include <stdio.h>
#include <xcb/xcb.h>

int i = 0;

int connect(xcb_connection_t** conn) {
    xcb_connection_t* try_conn = xcb_connect(NULL, NULL);
    int status = 0;
    int conn_status = xcb_connection_has_error(try_conn);
    if (conn_status != 0) {
        i = i + 1;
        switch (conn_status) {
            case XCB_CONN_ERROR:
                printf("Error connecting to the X Server, try %d\n", i);
                break;
            case XCB_CONN_CLOSED_EXT_NOTSUPPORTED:
                printf("Connection closed, extension not supported\n");
                break;
            case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
                printf("Connection closed, memory insufficient\n");
                break;
            case XCB_CONN_CLOSED_REQ_LEN_EXCEED:
                printf("Connection closed, required length exceeded\n");
                break;
            case XCB_CONN_CLOSED_PARSE_ERR:
                printf("Connection closed, parse error\n");
                break;
            case XCB_CONN_CLOSED_INVALID_SCREEN:
                printf("Connection closed, invalid screen\n");
                break;
            default:
                printf("Connection failed with unknown cause\n");
                break;
        }

        status = 1;
    } else {
        *conn = try_conn;
        status = 0;
    }

    return status;
}

int main() {
    xcb_connection_t* conn = NULL;
    if (connect(&conn) != 0) {
        printf("Error connecting to the X Server\n");
        return -1;
    }

    return 0;
}

It prints the line that says Error connecting the the X Server, try %d\n 8191 times every time I run the program. When I looked at what was going on with gdb, it seems like every time I call xcb_connect, my code goes into this deep recursion thing (like thousands of frames deep) between xcb_connect_to_display_with_auth_info() and my connect() function.

The part that really confuses me is how xcb_connect_to_display_with_auth_info() can even call my connect() function at all, because it's from a separate library and I haven't passed in a pointer to my function. My code looks to me like it's behavior should be completely "linear", but that's not the case at all.

I'm testing the window manager by running Xephyr with the X server name :1 and setting DISPLAY to :1 before running the program.

I'm somewhat new to XCB and C itself, so I'm probably missing something blatantly obvious, but I would appreciate any pointers. I've been looking at hootwm for inspiration mostly so far.


Solution

  • You are overriding the C library's connect function. XCB calls that function to connect to the X11 server, but instead ends up with calling your function instead. https://linux.die.net/man/2/connect

    One possible way out of this (besides giving your function another name) is to make it static.