bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: O_CLOEXEC support


From: Paolo Bonzini
Subject: Re: O_CLOEXEC support
Date: Thu, 20 Aug 2009 10:12:49 +0200
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.1) Gecko/20090814 Fedora/3.0-2.6.b3.fc11 Lightning/1.0pre Thunderbird/3.0b3

And this patch also includes a first use of O_CLOEXEC; I'm debating about
adding more O_CLOEXEC support throughout gnulib, a piece at a time.

You are beating me to it. :-)

And since fcntl is not portable, it
would be nice to add this convenience prototype to cloexec.h:

/* Return true if FD will not be inherited into child processes.  */
bool get_cloexec_flag (int fd);

Why not just implement a fcntl replacement, supporting only F_GETFD/F_SETFD for now (and maybe in the future F_DUPFD and F_DUPFD_CLOEXEC, as you mention below)? You mentioned this later in the email, but I read about it on the list in the past too, and it can be done as the very first step IMO.

open - Required by POSIX 2008 - We can't support atomic O_CLOEXEC if the
OS doesn't obey POSIX 2008, but we can at least fake it.  But not all
programs will be using O_CLOEXEC, so it seems like it is best to add a new
module open-cloexec

I'd rather keep the open module alone. However, there's an interesting thing that goes to our advantage. You cannot detect O_CLOEXEC at build-time, otherwise binary compatibility with older kernels goes south: I did this for GNU Smalltalk and two people reported that they needed to reboot to get GNU Smalltalk to run (because they had new kernel-headers and old kernel). So, if O_CLOEXEC is requested, you must _unconditionally_ use lib/open.c.

So, the open-cloexec module can be used simply as a guard and it would just do "gl_REPLACE_OPEN". At this point, just call it "cloexec".

 Implementation is simple - if
O_CLOEXEC is requested but the OS doesn't support it, then call
set_cloexec_handle after the fact in rpl_open.

Or call fcntl. :-)

pipe2, dup3, accept4, mkostemp - GNU/Linux extensions - New modules to
match recent glibc extensions around the recently added syscalls on Linux
for passing O_CLOEXEC (or O_NONBLOCK) via the flag argument.  Like open,
we can't support atomic cloexec fd creation, but can use
set_cloexec_handle as appropriate.  Any other fd creation functions I'm
forgetting?

socket(2). You can again set up the cloexec module to do gl_REPLACE_SOCKET unconditionally.

fcntl - required by POSIX 2008 - we still don't support all of the F_*
flags required by POSIX, and mingw doesn't have an fcntl to wrap, so
implementing a complete fcntl is daunting.  But maybe we could make a new
module fcntl-dupfd that handles just F_DUPFD and F_DUPFD_CLOEXEC on mingw,
and adds non-atomic F_DUPFD_CLOEXEC for all remaining lacking platforms.
Should we do this via the name rpl_fcntl, or wrap it in a named API more
like cloexec's set_cloexec_flag?

See above for my opinion.

Also, on mingw, I know of no way to open
the first free fd after a given point (the only arbitrary opening point is
via dup2, but that clobbers any existing fd), so we'd either have to loop
from the target until we find a free fd, or temporarily tie up all free
fds lower than the target (neither of which sounds thread-safe, but then
again I didn't promise atomic operation).

I think the usual way to do it is the same as dupfd in lib/dup2.c, only with an == replaced by >=:

int
dup_until (int fd, int target)
{
  int duped = dup (fd);
  if (duped < 0 || duped >= target)
    return duped;
  else
    {
      int result = dup_until (fd, target);
      int save_errno = errno;
      close (duped);
      errno = save_errno;
      return result;
    }
}

This is much more thread-safe than the alternative -- in fact it seems to me that it is thread-safe as long as the program does not blindly pass file descriptors that it does not own to close(2) or (as the second argument) to dup2(2).

fopen, fdopen, freopen, popen - glibc extensions - glibc recognizes 'e' in
the mode argument to stdio functions offers fopen (file, "re") as a
shortcut to use O_CLOEXEC under the hood.  Can be implemented with a
wrapper that filters the mode before calling the original function, then
calls set_cloexec_flag as appropriate.  Other flags like 'x' for O_EXCL
could also be implemented for fopen (using open/fdopen instead of wrapping
fopen).  Any other stream creation functions I'm forgetting?

fopen and popen are different.

You can expect to have platforms that suport O_CLOEXEC but not 'e', and you definitely want atomicity there, so the only useful way would be to reimplement fopen using open(2) and fdopen(3), which would be better because it allows 'x'/O_EXCL to be implemented too as you say. If the latter is considered useful, let's do it. But, I wouldn't bother about it, really.

For popen you couldn't do this at all, since pclose won't behave correctly for files opened with fdopen, so you wouldn't have atomicity. OTOH gnulib provides twenty-odd ways to open pipes, so let's figure out for which of these *defaulting* to close-on-exec would be a good idea, and let's flip the default there once the basic cloexec support is there.

For what I didn't answer (opendir, tmpfile) I don't know.

Paolo




reply via email to

[Prev in Thread] Current Thread [Next in Thread]