Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leaking DRI fds when vaInitialize() is called again on same VADisplay after failure #741

Open
cgutman opened this issue Aug 2, 2023 · 2 comments · May be fixed by #753
Open

Leaking DRI fds when vaInitialize() is called again on same VADisplay after failure #741

cgutman opened this issue Aug 2, 2023 · 2 comments · May be fixed by #753

Comments

@cgutman
Copy link

cgutman commented Aug 2, 2023

vaInitialize() doesn't clean up properly on failure, so subsequent calls to vaInitialize() will lead to leaks of a /dev/dri/card or /dev/dri/renderD file descriptor. Eventually the fd limit is reached and no more files can be opened, leading to a crash with a message similar to:

XIO:  fatal IO error 24 (Too many open files) on X server ":0"
      after 6 requests (6 known processed) with 0 events remaining.

Attempting to call vaInitialize() again after a failure might seem contrived at first glance, but it is a reasonable thing to do for clients that might be using vaSetDriverName() to try to get one driver over another.

Either the documentation should clearly state that vaTerminate() must be called even after a failed vaInitialize() call (which invalidates the whole VADisplay), or a failed vaInitialize() should leave the VADisplay in a clean state to allow another initialization attempt.

Reproducer:

gcc valeak.c -o valeak -lva -lva-x11 -lX11
#include <va/va.h>
#include <va/va_x11.h>
#include <X11/Xlib.h>

#include <stdlib.h>
#include <stdio.h>

int main() {
    Display *x11_disp = XOpenDisplay(NULL);
    if (!x11_disp) {
        fprintf(stderr, "Unable to open X11 display\n");
        return -1;
    }

    VADisplay va_disp = vaGetDisplay(x11_disp);
    if (!va_disp) {
        fprintf(stderr, "Unable to open VA display\n");
        return -1;
    }

    for (;;) {
        int major, minor;
        vaSetDriverName(va_disp, "NotARealDriver");
        VAStatus status = vaInitialize(va_disp, &major, &minor);
        if (status == VA_STATUS_SUCCESS) {
            fprintf(stderr, "vaInitialize() succeded with bogus driver name?\n");
            abort();
        }
        else {
            fprintf(stderr, "vaInitialize() failed: %s\n", vaErrorStr(status));
        }
    }
    
    vaTerminate(va_disp);
    XCloseDisplay(x11_disp);
}

Running lsof on the reproducer will show hundreds of leaked /dev/dri fds:

valeak  30432 cgutman  548u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  549u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  550u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  551u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  552u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  553u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  554u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  555u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  556u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  557u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  558u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  559u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  560u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  561u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  562u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  563u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  564u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  565u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  566u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  567u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  568u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  569u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  570u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  571u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  572u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  573u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  574u   CHR            226,128      0t0     571 /dev/dri/renderD128
valeak  30432 cgutman  575u   CHR            226,128      0t0     571 /dev/dri/renderD128
@XinfengZhang
Copy link
Contributor

there are two cases:

  1. DRM: the fd is opened by application, so libva could not close it. it is application responsibility to close the fd
  2. X11,Wayland: the fd is opened by libva, libva should destroy it by calling pDisplayContext->vaDestroy

@XinfengZhang
Copy link
Contributor

please help to review #753

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants