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