1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
#include <dirent.h>
#include <dlfcn.h>
#include <stdio.h>
#include <vdpau/vdpau.h>
#include <vdpau/vdpau_x11.h>
#include <X11/Xlib.h>
#define PASS 0
#define FAIL 1
#define SKIP 77
static int countOpenFDs(void)
{
DIR *dir = opendir("/proc/self/fd");
int count = 0;
if (!dir) {
fprintf(stderr, "Couldn't open /proc/self/fd; skipping file descriptor "
"leak test\n");
return 0;
}
while (readdir(dir) != NULL) {
count++;
}
closedir(dir);
return count;
}
#if defined(__sun)
static const char libXext_so[] = "libXext.so.0";
#else
static const char libXext_so[] = "libXext.so.6";
#endif
int main(void)
{
// Work around a bug in libXext: dlclosing it after it has registered the
// Generic Event Extension causes an identical bug to the one this program
// is trying to test for.
int nOpenFDs = countOpenFDs();
void *libXext = dlopen(libXext_so, RTLD_LAZY);
void *libvdpau = dlopen("src/libvdpau.so", RTLD_LAZY);
Display *dpy = XOpenDisplay(NULL);
VdpDeviceCreateX11 *pvdp_device_create_x11;
VdpDevice device;
VdpGetProcAddress *get_proc_address;
VdpStatus status;
if (!libXext) {
fprintf(stderr, "Failed to open %s: %s", libXext_so, dlerror());
return SKIP;
}
if (!libvdpau) {
fprintf(stderr, "Failed to open libvdpau.so: %s", dlerror());
return FAIL;
}
if (!dpy) {
fprintf(stderr, "Failed to connect to X display %s\n", XDisplayName(NULL));
return SKIP;
}
pvdp_device_create_x11 = dlsym(libvdpau, "vdp_device_create_x11");
if (!pvdp_device_create_x11) {
fprintf(stderr, "Failed to find the symbol vdp_device_create_x11\n");
return FAIL;
}
status = pvdp_device_create_x11(dpy, 0, &device, &get_proc_address);
if (status == VDP_STATUS_OK) {
// It's okay if creating the device fails. This will still install the
// DRI2 extension in libX11 and trigger the bug.
VdpDeviceDestroy *pvdp_device_destroy;
status = get_proc_address(device, VDP_FUNC_ID_DEVICE_DESTROY, (void**)&pvdp_device_destroy);
if (status != VDP_STATUS_OK) {
fprintf(stderr, "Failed to find the VdpDeviceDestroy function: %d\n", status);
return FAIL;
}
pvdp_device_destroy(device);
}
dlclose(libvdpau);
XCloseDisplay(dpy);
// Make sure no file descriptors were leaked.
if (countOpenFDs() != nOpenFDs) {
fprintf(stderr, "Mismatch in the number of open file descriptors!\n");
return FAIL;
}
return PASS;
}
|