2010/4/3 Kamil Dudka <[email protected]>:
> Hello,
>
> thanks for the new release of findutils in the first place!
>
> While I was trying to build packages for Fedora, I ran into huge test-suite
> failure.  For merely all tests the assertion within complain_about_leaky_fds
> () failed on the descriptor 3 or 4.
>
> Poking around, I discovered the function fd_is_cloexec () does not work
> there.  As it seems to be kernel specific, I haven't been able to reproduce
> it locally.

I suspect what's happening is that the library on your build hosts
defined O_CLOEXEC, but your kernel lacks support for it.   fcntl(fd,
F_GETFL) may just return the original flags we passed, meaning that
it's not a guarantee that the O_CLOEXEC actually had an effect.

Please test the attached alternative patch and let me know if it
solves your problem.

Thanks,
James.
From 8a6854d222ad62cfcbd9cbafb949751c2b3ed098 Mon Sep 17 00:00:00 2001
From: James Youngman <[email protected]>
Date: Sun, 4 Apr 2010 01:07:51 +0100
Subject: [PATCH] Fix open_cloexec on hosts which ignore O_CLOEXEC (i.e. old kernels).
To: [email protected]

* lib/fdleak.c (o_cloexec_works): New function, detects whether
the open flag O_CLOEXEC has any effect.
(open_cloexec): Call o_cloexec_works, just once, to find out
whether O_CLOEXEC is effective.  If not, set the close-on-exec
flag on fds by calling set_cloexec_flag.

Signed-off-by: James Youngman <[email protected]>
---
 ChangeLog    |    9 +++++++++
 lib/fdleak.c |   29 ++++++++++++++++++++++++++++-
 2 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b419405..cee57a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-04-04  James Youngman  <[email protected]>
+
+	Fix open_cloexec on hosts which ignore O_CLOEXEC (i.e. old kernels).
+	* lib/fdleak.c (o_cloexec_works): New function, detects whether
+	the open flag O_CLOEXEC has any effect.
+	(open_cloexec): Call o_cloexec_works, just once, to find out
+	whether O_CLOEXEC is effective.  If not, set the close-on-exec
+	flag on fds by calling set_cloexec_flag.
+
 2010-04-03  James Youngman  <[email protected]>
 
 	Move on from 4.5.7.
diff --git a/lib/fdleak.c b/lib/fdleak.c
index 2c362cf..02614c2 100644
--- a/lib/fdleak.c
+++ b/lib/fdleak.c
@@ -303,11 +303,27 @@ find_first_leaked_fd (const int* prev_non_cloexec_fds, size_t n)
   return context.leaked_fd;
 }
 
+static bool
+o_cloexec_works (void)
+{
+  bool result = false;
+  int fd = open ("/", O_RDONLY|O_CLOEXEC);
+  if (fd >= 0)
+    {
+      result = fd_is_cloexec (fd);
+      close (fd);
+    }
+  return result;
+}
+
+
 int
 open_cloexec (const char *path, int flags, ...)
 {
   int fd;
   mode_t mode = 0;
+  static bool cloexec_works = false;
+  static bool cloexec_status_known = false;
 
   if (flags & O_CREAT)
     {
@@ -322,8 +338,19 @@ open_cloexec (const char *path, int flags, ...)
       va_end (ap);
     }
 
+  /* Kernels usually ignore open flags they don't recognise, so it
+   * is possible this program was built against a library which
+   * defines O_CLOEXEC, but is running on a kernel that (silently)
+   * does not recognise it.   We figure this out by just trying it,
+   * once.
+   */
+  if (!cloexec_status_known)
+    {
+      cloexec_works = o_cloexec_works ();
+      cloexec_status_known = true;
+    }
   fd = open (path, flags|O_CLOEXEC, mode);
-  if ((fd >= 0) && !O_CLOEXEC)
+  if ((fd >= 0) && !(O_CLOEXEC && cloexec_works))
     {
       set_cloexec_flag (fd, true);
     }
-- 
1.7.0

Reply via email to