[Mesa-dev] Bug#651370: libgl1-mesa-glx: need close on exec for dri device

David Fries david at fries.net
Sat Dec 10 09:46:49 PST 2011


Set the close on exec flag when opening dri character devices, so they
will be closed and free any resouces allocated in exec.
---
Just for fun I included a git bundle of the commit.
Please Cc me on any replies as I'm not subscribed to the mesa list.

 src/egl/drivers/dri2/platform_wayland.c            |   11 ++++++++++-
 src/egl/drivers/dri2/platform_x11.c                |    9 +++++++++
 src/gallium/state_trackers/egl/drm/native_drm.c    |   11 ++++++++++-
 .../state_trackers/egl/fbdev/native_fbdev.c        |   11 ++++++++++-
 .../state_trackers/egl/wayland/native_drm.c        |   10 +++++++++-
 src/gallium/state_trackers/egl/x11/x11_screen.c    |   10 +++++++++-
 src/glx/dri2_glx.c                                 |   10 +++++++++-
 7 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 7a70d8d..2dfde69 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -747,7 +747,16 @@ drm_handle_device(void *data, struct wl_drm *drm, const char *device)
    if (!dri2_dpy->device_name)
       return;
 
-   dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
+#ifdef O_CLOEXEC
+   dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
+   if (dri2_dpy->fd == -1 && errno == EINVAL)
+#endif
+   {
+      dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
+      if (dri2_dpy->fd != -1)
+         fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) |
+            FD_CLOEXEC);
+   }
    if (dri2_dpy->fd == -1) {
       _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
 	      dri2_dpy->device_name, strerror(errno));
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index 8dd231a..a31a587 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -998,7 +998,16 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri2_load_driver(disp))
       goto cleanup_conn;
 
+#ifdef O_CLOEXEC
    dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
+   if (dri2_dpy->fd == -1 && errno == EINVAL)
+#endif
+   {
+      dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
+      if (dri2_dpy->fd != -1)
+         fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) |
+            FD_CLOEXEC);
+   }
    if (dri2_dpy->fd == -1) {
       _eglLog(_EGL_WARNING,
 	      "DRI2: could not open %s (%s)", dri2_dpy->device_name,
diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c
index c013769..a762f8f 100644
--- a/src/gallium/state_trackers/egl/drm/native_drm.c
+++ b/src/gallium/state_trackers/egl/drm/native_drm.c
@@ -312,7 +312,16 @@ native_create_display(void *dpy, boolean use_sw)
    gbm = dpy;
 
    if (gbm == NULL) {
-      fd = open("/dev/dri/card0", O_RDWR);
+      const char *device_name="/dev/dri/card0";
+#ifdef O_CLOEXEC
+      fd = open(device_name, O_RDWR | O_CLOEXEC);
+      if (fd == -1 && errno == EINVAL)
+#endif
+      {
+         fd = open(device_name, O_RDWR);
+         if (fd != -1)
+            fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+      }
       /* FIXME: Use an internal constructor to create a gbm
        * device with gallium backend directly, without setenv */
       setenv("GBM_BACKEND", "gbm_gallium_drm.so", 1);
diff --git a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c
index e126888..b45ab5c 100644
--- a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c
+++ b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c
@@ -515,7 +515,16 @@ native_create_display(void *dpy, boolean use_sw)
 
    /* well, this makes fd 0 being ignored */
    if (!dpy) {
-      fd = open("/dev/fb0", O_RDWR);
+      const char *device_name="/dev/fb0";
+#ifdef O_CLOEXEC
+      fd = open(device_name, O_RDWR | O_CLOEXEC);
+      if (fd == -1 && errno == EINVAL)
+#endif
+      {
+         fd = open(device_name, O_RDWR);
+         if (fd != -1)
+            fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+      }
    }
    else {
       fd = dup((int) pointer_to_intptr(dpy));
diff --git a/src/gallium/state_trackers/egl/wayland/native_drm.c b/src/gallium/state_trackers/egl/wayland/native_drm.c
index 5618f3e..92e73ed 100644
--- a/src/gallium/state_trackers/egl/wayland/native_drm.c
+++ b/src/gallium/state_trackers/egl/wayland/native_drm.c
@@ -134,7 +134,15 @@ drm_handle_device(void *data, struct wl_drm *drm, const char *device)
    if (!drmdpy->device_name)
       return;
 
-   drmdpy->fd = open(drmdpy->device_name, O_RDWR);
+#ifdef O_CLOEXEC
+   drmdpy->fd = open(drmdpy->device_name, O_RDWR | O_CLOEXEC);
+   if (drmdpy->fd == -1 && errno == EINVAL)
+#endif
+   {
+      drmdpy->fd = open(drmdpy->device_name, O_RDWR);
+      if (drmdpy->fd != -1)
+         fcntl(drmdpy->fd, F_SETFD, fcntl(drmdpy->fd, F_GETFD) | FD_CLOEXEC);
+   }
    if (drmdpy->fd == -1) {
       _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
               drmdpy->device_name, strerror(errno));
diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c
index 6155b4d..140668f 100644
--- a/src/gallium/state_trackers/egl/x11/x11_screen.c
+++ b/src/gallium/state_trackers/egl/x11/x11_screen.c
@@ -265,7 +265,15 @@ x11_screen_enable_dri2(struct x11_screen *xscr,
       if (!x11_screen_probe_dri2(xscr, NULL, NULL))
          return -1;
 
-      fd = open(xscr->dri_device, O_RDWR);
+#ifdef O_CLOEXEC
+      fd = open(xscr->dri_device, O_RDWR | O_CLOEXEC);
+      if (fd == -1 && errno == EINVAL)
+#endif
+      {
+         fd = open(xscr->dri_device, O_RDWR);
+         if (fd != -1)
+            fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+      }
       if (fd < 0) {
          _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device);
          return -1;
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index 553869a..b931a7b 100644
--- a/src/glx/dri2_glx.c
+++ b/src/glx/dri2_glx.c
@@ -914,7 +914,15 @@ dri2CreateScreen(int screen, struct glx_display * priv)
       goto handle_error;
    }
 
-   psc->fd = open(deviceName, O_RDWR);
+#ifdef O_CLOEXEC
+   psc->fd = open(deviceName, O_RDWR | O_CLOEXEC);
+   if (psc->fd == -1 && errno == EINVAL)
+#endif
+   {
+      psc->fd = open(deviceName, O_RDWR);
+      if (psc->fd != -1)
+         fcntl(psc->fd, F_SETFD, fcntl(psc->fd, F_GETFD) | FD_CLOEXEC);
+   }
    if (psc->fd < 0) {
       ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
       goto handle_error;
-- 
1.7.7.1


On Thu, Dec 08, 2011 at 08:37:46PM +0100, Julien Cristau wrote:
> On Wed, Dec  7, 2011 at 23:43:13 -0600, David Fries wrote:
> 
> > 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
> >  
> 
> I'd do something like
> 
> #ifdef O_CLOEXEC
>    dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
>    if (dri2_dpy->fd == -1 && errno == EINVAL)
> #endif
>    {
>       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);
>    }
>    if (dri2_dpy->fd == -1) {
>        _eglLog(...);
>        return;
> 
> so it still works if the build environment has O_CLOEXEC but the kernel
> doesn't support it at runtime.
> 
> Cheers,
> Julien
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mesa_cloexec_retry.bundle
Type: application/octet-stream
Size: 2747 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20111210/e40d6d84/attachment-0001.obj>


More information about the mesa-dev mailing list