[Mesa-dev] Bug#651370: libgl1-mesa-glx: need close on exec for dri device
Michel Dänzer
daenzer at debian.org
Thu Dec 8 01:06:20 PST 2011
On Mit, 2011-12-07 at 23:43 -0600, David Fries wrote:
> Package: libgl1-mesa-glx
>
> Version: 7.11-6
> Severity: normal
> Tags: patch
>
> When dri is used the character device /dev/dri/card0 is opened. That
> file descriptor should be set with the close on exec file as currently
> those resources are not released until it is closed, and exec causes
> those resources to be leaked until the process terminates. This was
> an extra problem for the program I'm working with as it will exec
> itself to start fresh and change modes, but will tie up additional
> OpenGL resources each time it does so.
>
> Here's a patch that will open it with O_CLOEXEC if available or set
> the FD_CLOEXEC flag otherwise. It almost seems like there should be a
> common function such as open_wr_cloexec that will make sure and set
> the flag, but I didn't see an appropriate header file to put it in.
Can you create a patch against upstream Git with git format-patch and
send it to the mesa-dev mailing list (CC'd) for review?
> diff -upr /tmp/mesa-7.11/src/egl/drivers/dri2/platform_wayland.c mesa-7.11/src/egl/drivers/dri2/platform_wayland.c
> --- /tmp/mesa-7.11/src/egl/drivers/dri2/platform_wayland.c 2011-07-08 20:37:09.000000000 -0500
> +++ mesa-7.11/src/egl/drivers/dri2/platform_wayland.c 2011-12-07 21:28:10.000000000 -0600
> @@ -734,17 +734,25 @@ drm_handle_device(void *data, struct wl_
> {
> struct dri2_egl_display *dri2_dpy = data;
> drm_magic_t magic;
> +#ifdef O_CLOEXEC
> + int flags = O_RDWR | O_CLOEXEC;
> +#else
> + int flags = O_RDWR;
> +#endif
>
> dri2_dpy->device_name = strdup(device);
> if (!dri2_dpy->device_name)
> return;
>
> - dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
> + dri2_dpy->fd = open(dri2_dpy->device_name, flags);
> if (dri2_dpy->fd == -1) {
> _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
> dri2_dpy->device_name, strerror(errno));
> return;
> }
> +#ifndef O_CLOEXEC
> + fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | FD_CLOEXEC);
> +#endif
>
> drmGetMagic(dri2_dpy->fd, &magic);
> wl_drm_authenticate(dri2_dpy->wl_drm, magic);
> diff -upr /tmp/mesa-7.11/src/egl/drivers/dri2/platform_x11.c mesa-7.11/src/egl/drivers/dri2/platform_x11.c
> --- /tmp/mesa-7.11/src/egl/drivers/dri2/platform_x11.c 2011-12-07 20:53:39.000000000 -0600
> +++ mesa-7.11/src/egl/drivers/dri2/platform_x11.c 2011-12-07 21:28:09.000000000 -0600
> @@ -961,6 +961,11 @@ static EGLBoolean
> dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
> {
> struct dri2_egl_display *dri2_dpy;
> +#ifdef O_CLOEXEC
> + int flags = O_RDWR | O_CLOEXEC;
> +#else
> + int flags = O_RDWR;
> +#endif
>
> drv->API.CreateWindowSurface = dri2_create_window_surface;
> drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
> @@ -997,19 +1002,16 @@ dri2_initialize_x11_dri2(_EGLDriver *drv
> if (!dri2_load_driver(disp))
> goto cleanup_conn;
>
> -#ifdef O_CLOEXEC
> - dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
> -#else
> - dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
> - if (dri2_dpy->fd >= 0)
> - fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | FD_CLOEXEC);
> -#endif
> + dri2_dpy->fd = open(dri2_dpy->device_name, flags);
> if (dri2_dpy->fd == -1) {
> _eglLog(_EGL_WARNING,
> "DRI2: could not open %s (%s)", dri2_dpy->device_name,
> strerror(errno));
> goto cleanup_driver;
> }
> +#ifndef O_CLOEXEC
> + fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | FD_CLOEXEC);
> +#endif
>
> if (dri2_dpy->conn) {
> if (!dri2_authenticate(disp))
> diff -upr /tmp/mesa-7.11/src/gallium/state_trackers/egl/drm/native_drm.c mesa-7.11/src/gallium/state_trackers/egl/drm/native_drm.c
> --- /tmp/mesa-7.11/src/gallium/state_trackers/egl/drm/native_drm.c 2011-07-14 12:42:59.000000000 -0500
> +++ mesa-7.11/src/gallium/state_trackers/egl/drm/native_drm.c 2011-12-07 21:28:09.000000000 -0600
> @@ -302,11 +302,20 @@ native_create_display(void *dpy, boolean
> {
> struct gbm_gallium_drm_device *gbm;
> int fd;
> +#ifdef O_CLOEXEC
> + int flags = O_RDWR | O_CLOEXEC;
> +#else
> + int flags = O_RDWR;
> +#endif
>
> gbm = dpy;
>
> if (gbm == NULL) {
> - fd = open("/dev/dri/card0", O_RDWR);
> + fd = open("/dev/dri/card0", flags);
> +#ifndef O_CLOEXEC
> + if (fd != -1)
> + fcntl(fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | FD_CLOEXEC);
> +#endif
> gbm = gbm_gallium_drm_device(gbm_create_device(fd));
> }
>
> diff -upr /tmp/mesa-7.11/src/gallium/state_trackers/egl/fbdev/native_fbdev.c mesa-7.11/src/gallium/state_trackers/egl/fbdev/native_fbdev.c
> --- /tmp/mesa-7.11/src/gallium/state_trackers/egl/fbdev/native_fbdev.c 2011-07-08 20:37:09.000000000 -0500
> +++ mesa-7.11/src/gallium/state_trackers/egl/fbdev/native_fbdev.c 2011-12-07 21:28:09.000000000 -0600
> @@ -514,16 +514,24 @@ native_create_display(void *dpy, boolean
> {
> struct native_display *ndpy;
> int fd;
> +#ifdef O_CLOEXEC
> + int flags = O_RDWR | O_CLOEXEC;
> +#else
> + int flags = O_RDWR;
> +#endif
>
> /* well, this makes fd 0 being ignored */
> if (!dpy) {
> - fd = open("/dev/fb0", O_RDWR);
> + fd = open("/dev/fb0", flags);
> }
> else {
> fd = dup((int) pointer_to_intptr(dpy));
> }
> if (fd < 0)
> return NULL;
> +#ifndef O_CLOEXEC
> + fcntl(fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | FD_CLOEXEC);
> +#endif
>
> ndpy = fbdev_display_create(fd, fbdev_event_handler);
> if (!ndpy)
> diff -upr /tmp/mesa-7.11/src/gallium/state_trackers/egl/wayland/native_drm.c mesa-7.11/src/gallium/state_trackers/egl/wayland/native_drm.c
> --- /tmp/mesa-7.11/src/gallium/state_trackers/egl/wayland/native_drm.c 2011-07-08 20:37:09.000000000 -0500
> +++ mesa-7.11/src/gallium/state_trackers/egl/wayland/native_drm.c 2011-12-07 21:28:09.000000000 -0600
> @@ -146,17 +146,25 @@ drm_handle_device(void *data, struct wl_
> {
> struct wayland_drm_display *drmdpy = data;
> drm_magic_t magic;
> +#ifdef O_CLOEXEC
> + int flags = O_RDWR | O_CLOEXEC;
> +#else
> + int flags = O_RDWR;
> +#endif
>
> drmdpy->device_name = strdup(device);
> if (!drmdpy->device_name)
> return;
>
> - drmdpy->fd = open(drmdpy->device_name, O_RDWR);
> + drmdpy->fd = open(drmdpy->device_name, flags);
> if (drmdpy->fd == -1) {
> _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
> drmdpy->device_name, strerror(errno));
> return;
> }
> +#ifndef O_CLOEXEC
> + fcntl(drmdpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | FD_CLOEXEC);
> +#endif
>
> drmGetMagic(drmdpy->fd, &magic);
> wl_drm_authenticate(drmdpy->wl_drm, magic);
> diff -upr /tmp/mesa-7.11/src/gallium/state_trackers/egl/x11/x11_screen.c mesa-7.11/src/gallium/state_trackers/egl/x11/x11_screen.c
> --- /tmp/mesa-7.11/src/gallium/state_trackers/egl/x11/x11_screen.c 2011-07-08 20:37:09.000000000 -0500
> +++ mesa-7.11/src/gallium/state_trackers/egl/x11/x11_screen.c 2011-12-07 21:28:09.000000000 -0600
> @@ -260,16 +260,24 @@ x11_screen_enable_dri2(struct x11_screen
> if (xscr->dri_fd < 0) {
> int fd;
> drm_magic_t magic;
> +#ifdef O_CLOEXEC
> + int flags = O_RDWR | O_CLOEXEC;
> +#else
> + int flags = O_RDWR;
> +#endif
>
> /* get the driver name and the device name first */
> if (!x11_screen_probe_dri2(xscr, NULL, NULL))
> return -1;
>
> - fd = open(xscr->dri_device, O_RDWR);
> + fd = open(xscr->dri_device, flags);
> if (fd < 0) {
> _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device);
> return -1;
> }
> +#ifndef O_CLOEXEC
> + fcntl(fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | FD_CLOEXEC);
> +#endif
>
> memset(&magic, 0, sizeof(magic));
> if (drmGetMagic(fd, &magic)) {
> diff -upr /tmp/mesa-7.11/src/glx/dri2_glx.c mesa-7.11/src/glx/dri2_glx.c
> --- /tmp/mesa-7.11/src/glx/dri2_glx.c 2011-07-08 20:37:10.000000000 -0500
> +++ mesa-7.11/src/glx/dri2_glx.c 2011-12-07 21:28:09.000000000 -0600
> @@ -815,6 +815,11 @@ dri2CreateScreen(int screen, struct glx_
> char *driverName, *deviceName;
> drm_magic_t magic;
> int i;
> +#ifdef O_CLOEXEC
> + int flags = O_RDWR | O_CLOEXEC;
> +#else
> + int flags = O_RDWR;
> +#endif
>
> psc = Xmalloc(sizeof *psc);
> if (psc == NULL)
> @@ -859,11 +864,14 @@ dri2CreateScreen(int screen, struct glx_
> goto handle_error;
> }
>
> - psc->fd = open(deviceName, O_RDWR);
> + psc->fd = open(deviceName, flags);
> if (psc->fd < 0) {
> ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
> goto handle_error;
> }
> +#ifndef O_CLOEXEC
> + fcntl(psc->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | FD_CLOEXEC);
> +#endif
>
> if (drmGetMagic(psc->fd, &magic)) {
> ErrorMessageF("failed to get magic\n");
--
Earthling Michel Dänzer | http://www.amd.com
Libre software enthusiast | Debian, X and DRI developer
More information about the mesa-dev
mailing list