SDL_Init is not stable in a Xvfb virtual X server (docker) env

I’m using SDL-2.0.10 (default apt install version with Ubuntu-20.04) in docker env, here is my main Dockerfile libraries setup:

# try setup Xvfb+mesa headless X env: xorg xorg-dev?
RUN apt-get update && apt-get install -y mesa-utils xvfb libglvnd-dev libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev mesa-utils-extra

# install gstreamer for X app window capture:
RUN apt-get update && apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

# SDL2 & other deps:
RUN apt-get update && apt-get install -y libsdl2-dev libfreetype-dev libharfbuzz-dev libglib2.0-dev libpng-dev libunwind-dev libfontconfig1-dev libicu-dev libcurl4-openssl-dev libssl-dev

My SDL2 test code init is:

    const int windowWidth = 1280;
    const int windowHeight = 720;
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        printf("Init SDL failed '%s' !\n", SDL_GetError());
        return 0;

    SDL_Window *window = SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED
        , SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, SDL_WINDOW_ALLOW_HIGHDPI);
    if (NULL == window) {
        printf("SDL could not create window with error: %s\n", SDL_GetError());
        return 0;

My cmd is: xvfb-run ./test which auto creates a Display and set DISPLAY env var.
However, app frequently reports:

error: XDG_RUNTIME_DIR not set in the environment.
Init SDL failed 'No available video device' !

I’ve tracked to X11_CreateDevice function:

static SDL_VideoDevice *
X11_CreateDevice(int devindex)
    SDL_VideoDevice *device;
    SDL_VideoData *data;
    const char *display = NULL; /* Use the DISPLAY environment variable */

    if (!SDL_X11_LoadSymbols()) {
        return NULL;

    /* Need for threading gl calls. This is also required for the proprietary
        nVidia driver to be threaded. */

    /* Initialize all variables that we clean on shutdown */
    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
    if (!device) {
        return NULL;
    data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
    if (!data) {
        return NULL;
    device->driverdata = data;

    data->global_mouse_changed = SDL_TRUE;

    /* FIXME: Do we need this?
       if ( (SDL_strncmp(X11_XDisplayName(display), ":", 1) == 0) ||
       (SDL_strncmp(X11_XDisplayName(display), "unix:", 5) == 0) ) {
       local_X11 = 1;
       } else {
       local_X11 = 0;
    data->display = X11_XOpenDisplay(display);
    /* On some systems if linking without -lX11, it fails and you get following message.
     * Xlib: connection to ":0.0" refused by server
     * Xlib: XDM authorization key matches an existing client!
     * It succeeds if retrying 1 second later
     * or if running xhost +localhost on shell.
    if (data->display == NULL) {
        data->display = X11_XOpenDisplay(display);
    if (data->display == NULL) {
        SDL_SetError("Couldn't open X11 display");
        return NULL;

Since there is no SDL_OutOfMemory() related error message, i doubt the root cause is in SDL_X11_LoadSymbols

Can anyone here help? thanks.

PS: when i comment out the line apt-get install -y libsdl2-dev & install SDL2 from source, using the docker cmd:

ADD SDL2-2.0.10.tar.gz /
RUN cd /SDL2-2.0.10 && ./configure && make && make install

the problem seems gone away (or at least mitigated) …

Update: after i install SDL2-2.0.10 from source tar ball, the problem gone away (but not applicable with latest 2.0.16)


RUN curl -s -o SDL2-2.0.10.tar.gz \
  && tar xf SDL2-2.0.10.tar.gz \
  && cd /SDL2-2.0.10 && ./configure && make && make install \
  && cd / && rm -rf /SDL2-2.0.10 SDL2-2.0.10.tar.gz