<div dir="ltr">How old? O_CLOEXEC is part of the 2008 POSIX specification. I really wouldn't like to build on anything older than that... :(<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Sep 22, 2014 at 1:24 PM, Aaron Plattner <span dir="ltr"><<a href="mailto:aplattner@nvidia.com" target="_blank">aplattner@nvidia.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Old versions of Linux don't support O_CLOEXEC, so rather than failing to build,<br>
allow building without O_CLOEXEC if a new ALLOW_NO_O_CLOEXEC flag is defined.<br>
<br>
Create a new helper function, pci_open_cloexec that uses O_CLOEXEC when it's<br>
available and falls back to open + fcntl when it's not.  Route all calls to open<br>
that pass O_CLOEXEC through this new function instead using the following<br>
Coccinelle patch:<br>
<br>
  @@<br>
  expression path, flags;<br>
  @@<br>
  -open(path, flags | O_CLOEXEC)<br>
  +pci_open_cloexec(path, flags)<br>
<br>
Signed-off-by: Aaron Plattner <<a href="mailto:aplattner@nvidia.com">aplattner@nvidia.com</a>><br>
---<br>
There are three calls to open() that don't use O_CLOEXEC -- are those bugs?<br>
<br>
src/linux_devmem.c:    fd = open("/dev/mem", O_RDONLY, 0);<br>
src/netbsd_pci.c:       fd = open("/dev/ttyE0", O_RDONLY);<br>
src/netbsd_pci.c:               pcifd = open(netbsd_devname, O_RDWR);<br>
<br>
 src/common_vgaarb.c     |  2 +-<br>
 src/freebsd_pci.c       | 10 +++++-----<br>
 src/linux_sysfs.c       | 26 +++++++++++++-------------<br>
 src/netbsd_pci.c        |  2 +-<br>
 src/openbsd_pci.c       |  2 +-<br>
 src/pciaccess_private.h | 33 +++++++++++++++++++++++++++++----<br>
 src/solx_devfs.c        |  4 ++--<br>
 src/x86_pci.c           |  4 ++--<br>
 8 files changed, 54 insertions(+), 29 deletions(-)<br>
<br>
diff --git a/src/common_vgaarb.c b/src/common_vgaarb.c<br>
index c59bd788dc5e..f3b523e67c3a 100644<br>
--- a/src/common_vgaarb.c<br>
+++ b/src/common_vgaarb.c<br>
@@ -131,7 +131,7 @@ pci_device_vgaarb_init(void)<br>
     if (!pci_sys)<br>
         return -1;<br>
<br>
-    if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR | O_CLOEXEC)) < 0) {<br>
+    if ((pci_sys->vgaarb_fd = pci_open_cloexec ("/dev/vga_arbiter", O_RDWR)) < 0) {<br>
         return errno;<br>
     }<br>
<br>
diff --git a/src/freebsd_pci.c b/src/freebsd_pci.c<br>
index 9505a1c17d21..e40d80847bf0 100644<br>
--- a/src/freebsd_pci.c<br>
+++ b/src/freebsd_pci.c<br>
@@ -112,7 +112,7 @@ pci_device_freebsd_map_range(struct pci_device *dev,<br>
<br>
     int fd, err = 0;<br>
<br>
-    fd = open("/dev/mem", O_RDWR | O_CLOEXEC);<br>
+    fd = pci_open_cloexec("/dev/mem", O_RDWR);<br>
     if (fd == -1)<br>
        return errno;<br>
<br>
@@ -157,7 +157,7 @@ pci_device_freebsd_unmap_range( struct pci_device *dev,<br>
     if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||<br>
        (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE))<br>
     {<br>
-       fd = open("/dev/mem", O_RDWR | O_CLOEXEC);<br>
+       fd = pci_open_cloexec("/dev/mem", O_RDWR);<br>
        if (fd != -1) {<br>
            mrd.mr_base = map->base;<br>
            mrd.mr_len = map->size;<br>
@@ -297,7 +297,7 @@ pci_device_freebsd_read_rom( struct pci_device * dev, void * buffer )<br>
     }<br>
<br>
     printf("Using rom_base = 0x%lx\n", (long)rom_base);<br>
-    memfd = open( "/dev/mem", O_RDONLY | O_CLOEXEC );<br>
+    memfd = pci_open_cloexec( "/dev/mem", O_RDONLY );<br>
     if ( memfd == -1 )<br>
        return errno;<br>
<br>
@@ -574,7 +574,7 @@ pci_device_freebsd_open_legacy_io(struct pci_io_handle *ret,<br>
     struct pci_device *dev, pciaddr_t base, pciaddr_t size)<br>
 {<br>
 #if defined(__i386__) || defined(__amd64__)<br>
-       ret->fd = open("/dev/io", O_RDWR | O_CLOEXEC);<br>
+       ret->fd = pci_open_cloexec("/dev/io", O_RDWR);<br>
<br>
        if (ret->fd < 0)<br>
                return NULL;<br>
@@ -735,7 +735,7 @@ pci_system_freebsd_create( void )<br>
     int i;<br>
<br>
     /* Try to open the PCI device */<br>
-    pcidev = open( "/dev/pci", O_RDWR | O_CLOEXEC );<br>
+    pcidev = pci_open_cloexec( "/dev/pci", O_RDWR );<br>
     if ( pcidev == -1 )<br>
        return ENXIO;<br>
<br>
diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c<br>
index 08c99719bcba..120cd6411893 100644<br>
--- a/src/linux_sysfs.c<br>
+++ b/src/linux_sysfs.c<br>
@@ -100,7 +100,7 @@ pci_system_linux_sysfs_create( void )<br>
        if ( pci_sys != NULL ) {<br>
            pci_sys->methods = & linux_sysfs_methods;<br>
 #ifdef HAVE_MTRR<br>
-           pci_sys->mtrr_fd = open("/proc/mtrr", O_WRONLY | O_CLOEXEC);<br>
+           pci_sys->mtrr_fd = pci_open_cloexec("/proc/mtrr", O_WRONLY);<br>
 #endif<br>
            err = populate_entries(pci_sys);<br>
        }<br>
@@ -247,7 +247,7 @@ pci_device_linux_sysfs_probe( struct pci_device * dev )<br>
                  dev->bus,<br>
                  dev->dev,<br>
                  dev->func );<br>
-       fd = open( name, O_RDONLY | O_CLOEXEC);<br>
+       fd = pci_open_cloexec(name, O_RDONLY);<br>
        if ( fd != -1 ) {<br>
            char * next;<br>
            pciaddr_t  low_addr;<br>
@@ -309,7 +309,7 @@ pci_device_linux_sysfs_read_rom( struct pci_device * dev, void * buffer )<br>
              dev->dev,<br>
              dev->func );<br>
<br>
-    fd = open( name, O_RDWR | O_CLOEXEC);<br>
+    fd = pci_open_cloexec(name, O_RDWR);<br>
     if ( fd == -1 ) {<br>
 #ifdef LINUX_ROM<br>
        /* If reading the ROM using sysfs fails, fall back to the old<br>
@@ -390,7 +390,7 @@ pci_device_linux_sysfs_read( struct pci_device * dev, void * data,<br>
              dev->dev,<br>
              dev->func );<br>
<br>
-    fd = open( name, O_RDONLY | O_CLOEXEC);<br>
+    fd = pci_open_cloexec(name, O_RDONLY);<br>
     if ( fd == -1 ) {<br>
        return errno;<br>
     }<br>
@@ -450,7 +450,7 @@ pci_device_linux_sysfs_write( struct pci_device * dev, const void * data,<br>
              dev->dev,<br>
              dev->func );<br>
<br>
-    fd = open( name, O_WRONLY | O_CLOEXEC);<br>
+    fd = pci_open_cloexec(name, O_WRONLY);<br>
     if ( fd == -1 ) {<br>
        return errno;<br>
     }<br>
@@ -501,7 +501,7 @@ pci_device_linux_sysfs_map_range_wc(struct pci_device *dev,<br>
             dev->dev,<br>
             dev->func,<br>
             map->region);<br>
-    fd = open(name, open_flags | O_CLOEXEC);<br>
+    fd = pci_open_cloexec(name, open_flags);<br>
     if (fd == -1)<br>
            return errno;<br>
<br>
@@ -566,7 +566,7 @@ pci_device_linux_sysfs_map_range(struct pci_device *dev,<br>
              dev->func,<br>
              map->region);<br>
<br>
-    fd = open(name, open_flags | O_CLOEXEC);<br>
+    fd = pci_open_cloexec(name, open_flags);<br>
     if (fd == -1) {<br>
         return errno;<br>
     }<br>
@@ -689,7 +689,7 @@ static void pci_device_linux_sysfs_enable(struct pci_device *dev)<br>
              dev->dev,<br>
              dev->func );<br>
<br>
-    fd = open( name, O_RDWR | O_CLOEXEC);<br>
+    fd = pci_open_cloexec(name, O_RDWR);<br>
     if (fd == -1)<br>
        return;<br>
<br>
@@ -711,7 +711,7 @@ static int pci_device_linux_sysfs_boot_vga(struct pci_device *dev)<br>
              dev->dev,<br>
              dev->func );<br>
<br>
-    fd = open( name, O_RDONLY | O_CLOEXEC);<br>
+    fd = pci_open_cloexec(name, O_RDONLY);<br>
     if (fd == -1)<br>
        return 0;<br>
<br>
@@ -754,7 +754,7 @@ pci_device_linux_sysfs_open_device_io(struct pci_io_handle *ret,<br>
     snprintf(name, PATH_MAX, "%s/%04x:%02x:%02x.%1u/resource%d",<br>
             SYS_BUS_PCI, dev->domain, dev->bus, dev->dev, dev->func, bar);<br>
<br>
-    ret->fd = open(name, O_RDWR | O_CLOEXEC);<br>
+    ret->fd = pci_open_cloexec(name, O_RDWR);<br>
<br>
     if (ret->fd < 0)<br>
        return NULL;<br>
@@ -778,7 +778,7 @@ pci_device_linux_sysfs_open_legacy_io(struct pci_io_handle *ret,<br>
        snprintf(name, PATH_MAX, "/sys/class/pci_bus/%04x:%02x/legacy_io",<br>
                 dev->domain, dev->bus);<br>
<br>
-       ret->fd = open(name, O_RDWR | O_CLOEXEC);<br>
+       ret->fd = pci_open_cloexec(name, O_RDWR);<br>
        if (ret->fd >= 0)<br>
            break;<br>
<br>
@@ -925,7 +925,7 @@ pci_device_linux_sysfs_map_legacy(struct pci_device *dev, pciaddr_t base,<br>
        snprintf(name, PATH_MAX, "/sys/class/pci_bus/%04x:%02x/legacy_mem",<br>
                 dev->domain, dev->bus);<br>
<br>
-       fd = open(name, flags | O_CLOEXEC);<br>
+       fd = pci_open_cloexec(name, flags);<br>
        if (fd >= 0)<br>
            break;<br>
<br>
@@ -934,7 +934,7 @@ pci_device_linux_sysfs_map_legacy(struct pci_device *dev, pciaddr_t base,<br>
<br>
     /* If not, /dev/mem is the best we can do */<br>
     if (!dev)<br>
-       fd = open("/dev/mem", flags | O_CLOEXEC);<br>
+       fd = pci_open_cloexec("/dev/mem", flags);<br>
<br>
     if (fd < 0)<br>
        return errno;<br>
diff --git a/src/netbsd_pci.c b/src/netbsd_pci.c<br>
index 52591b08f737..87bb2feb2504 100644<br>
--- a/src/netbsd_pci.c<br>
+++ b/src/netbsd_pci.c<br>
@@ -909,7 +909,7 @@ pci_system_netbsd_create(void)<br>
        ndevs = 0;<br>
        nbuses = 0;<br>
        snprintf(netbsd_devname, 32, "/dev/pci%d", nbuses);<br>
-       pcifd = open(netbsd_devname, O_RDWR | O_CLOEXEC);<br>
+       pcifd = pci_open_cloexec(netbsd_devname, O_RDWR);<br>
        while (pcifd > 0) {<br>
                ioctl(pcifd, PCI_IOC_BUSINFO, &businfo);<br>
                buses[nbuses].fd = pcifd;<br>
diff --git a/src/openbsd_pci.c b/src/openbsd_pci.c<br>
index fe034f3b046b..3d66598b5b77 100644<br>
--- a/src/openbsd_pci.c<br>
+++ b/src/openbsd_pci.c<br>
@@ -571,7 +571,7 @@ pci_system_openbsd_create(void)<br>
<br>
        for (domain = 0; domain < sizeof(pcifd) / sizeof(pcifd[0]); domain++) {<br>
                snprintf(path, sizeof(path), "/dev/pci%d", domain);<br>
-               pcifd[domain] = open(path, O_RDWR | O_CLOEXEC);<br>
+               pcifd[domain] = pci_open_cloexec(path, O_RDWR);<br>
                if (pcifd[domain] == -1)<br>
                        break;<br>
                ndomains++;<br>
diff --git a/src/pciaccess_private.h b/src/pciaccess_private.h<br>
index 9f4e8f9ab573..0de989bceab4 100644<br>
--- a/src/pciaccess_private.h<br>
+++ b/src/pciaccess_private.h<br>
@@ -40,13 +40,16 @@<br>
 /*<br>
  * O_CLOEXEC fixes an fd leak case (see 'man 2 open' for details). I don't<br>
  * know of any OS we support where this isn't available in a sufficiently<br>
- * new version, so warn unconditionally.<br>
+ * new version, so fail if ALLOW_NO_O_CLOEXEC is not defined.<br>
  */<br>
 #include <sys/fcntl.h><br>
<br>
-#ifndef O_CLOEXEC<br>
-#warning O_CLOEXEC not available, please upgrade.<br>
-#define O_CLOEXEC 0<br>
+#if !defined(O_CLOEXEC)<br>
+# if defined(ALLOW_NO_O_CLOEXEC)<br>
+#  include <unistd.h><br>
+# else<br>
+#  error O_CLOEXEC not available, please upgrade.<br>
+# endif<br>
 #endif<br>
<br>
<br>
@@ -191,3 +194,25 @@ extern void pci_system_openbsd_init_dev_mem( int );<br>
 extern int pci_system_solx_devfs_create( void );<br>
 extern int pci_system_x86_create( void );<br>
 extern void pci_io_cleanup( void );<br>
+<br>
+static inline int pci_open_cloexec( const char *path, int flags )<br>
+{<br>
+#if defined(O_CLOEXEC)<br>
+    return open(path, flags | O_CLOEXEC);<br>
+#else<br>
+    int fd = open(path, flags);<br>
+    if (fd >= 0) {<br>
+       int flags = fcntl(fd, F_GETFD);<br>
+       if (flags == -1) {<br>
+           close(fd);<br>
+           return -1;<br>
+       }<br>
+       flags |= FD_CLOEXEC;<br>
+       if (fcntl(fd, F_SETFD, flags) == -1) {<br>
+           close(fd);<br>
+           return -1;<br>
+       }<br>
+    }<br>
+    return fd;<br>
+#endif<br>
+}<br>
diff --git a/src/solx_devfs.c b/src/solx_devfs.c<br>
index f57239304a43..2d4b102f8cf1 100644<br>
--- a/src/solx_devfs.c<br>
+++ b/src/solx_devfs.c<br>
@@ -415,7 +415,7 @@ probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)<br>
            nexus_path, first_bus, last_bus);<br>
 #endif<br>
<br>
-    if ((fd = open(nexus_path, O_RDWR | O_CLOEXEC)) >= 0) {<br>
+    if ((fd = pci_open_cloexec(nexus_path, O_RDWR)) >= 0) {<br>
        probe_args_t args;<br>
<br>
        nexus->fd = fd;<br>
@@ -718,7 +718,7 @@ pci_device_solx_devfs_map_range(struct pci_device *dev,<br>
 #endif<br>
<br>
     if (map_fd < 0) {<br>
-       if ((map_fd = open(map_dev, O_RDWR | O_CLOEXEC)) < 0) {<br>
+       if ((map_fd = pci_open_cloexec(map_dev, O_RDWR)) < 0) {<br>
            err = errno;<br>
            (void) fprintf(stderr, "can not open %s: %s\n", map_dev,<br>
                           strerror(errno));<br>
diff --git a/src/x86_pci.c b/src/x86_pci.c<br>
index 49c1cabc3c6c..7088ff9a016d 100644<br>
--- a/src/x86_pci.c<br>
+++ b/src/x86_pci.c<br>
@@ -457,7 +457,7 @@ pci_device_x86_read_rom(struct pci_device *dev, void *buffer)<br>
        return ENOSYS;<br>
     }<br>
<br>
-    memfd = open("/dev/mem", O_RDONLY | O_CLOEXEC);<br>
+    memfd = pci_open_cloexec("/dev/mem", O_RDONLY);<br>
     if (memfd == -1)<br>
        return errno;<br>
<br>
@@ -637,7 +637,7 @@ static int<br>
 pci_device_x86_map_range(struct pci_device *dev,<br>
     struct pci_device_mapping *map)<br>
 {<br>
-    int memfd = open("/dev/mem", O_RDWR | O_CLOEXEC);<br>
+    int memfd = pci_open_cloexec("/dev/mem", O_RDWR);<br>
     int prot = PROT_READ;<br>
<br>
     if (memfd == -1)<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.1.0<br>
<br>
_______________________________________________<br>
<a href="mailto:xorg-devel@lists.x.org">xorg-devel@lists.x.org</a>: X.Org development<br>
Archives: <a href="http://lists.x.org/archives/xorg-devel" target="_blank">http://lists.x.org/archives/xorg-devel</a><br>
Info: <a href="http://lists.x.org/mailman/listinfo/xorg-devel" target="_blank">http://lists.x.org/mailman/listinfo/xorg-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>  Jasper<br>
</div>