bug-gnulib
[Top][All Lists]
Advanced

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

O_CLOEXEC support (was: popen bugs, popen_safer)


From: Eric Blake
Subject: O_CLOEXEC support (was: popen bugs, popen_safer)
Date: Wed, 19 Aug 2009 12:11:24 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.22) Gecko/20090605 Thunderbird/2.0.0.22 Mnenhy/0.7.6.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 8/19/2009 11:06 AM:
> I went ahead and implemented popen_safer.

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.
cloexec support has two benefits - fewer syscalls on newer kernels, and
multithread safety (closing the window where a second thread can do a
fork/exec and leak an fd during the window of the first thread doing fd
creation and fcntl).  Without atomic cloexec support from the kernel, we
can't avoid the race (short of wrapping a mutex around every call to any
function that might create an fd, including library functions that might
temporarily open an fd under the hood); but most gnulib clients are
single-threaded and would at least benefit from a speedup due to fewer
kernel calls.  Thoughts before I start tackling this?

cloexec - convenience wrapper - On mingw, there is no fcntl or FD_CLOEXEC,
however, the primary semantics of FD_CLOEXEC (making an fd invisible to
exec'd child processes) maps very well to win32 O_NOINHERIT.  w32spawn.h
has dup_noinherit that tweaks the O_NOINHERIT flag, but we also need to
tweak the O_NOINHERIT flag of an existing fd without having to use dup in
cloexec.c (I'm hoping the windows functions GetHandleInformation and
SetHandleInformation work here).  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);

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, and only add O_CLOEXEC support if the module is
requested rather than blindly wrap open.  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.

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?

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?  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).

accept, pipe, dup2, mkstemp - no way to pass flag information, hence the
glibc extensions accept4, pipe2, dup3, mkostemp

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?

opendir - no way to pass flags, but the fd is already treated as cloexec
per POSIX rules (whether or not it is actually marked cloexec); no changes
needed.  Are there any OS's out there that disobey POSIX and leak an open
directory fd into child processes?

tmpfile - no way to pass flag information.  Is there any glibc analog to
tmpfile that takes flags?  Meanwhile, we have the gnulib module clean-tmp,
but open_temp and fopen_temp should be able to use the same flags as open
and fopen, so it seems like no changes are needed on that front

anything else?

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkqMQEwACgkQ84KuGfSFAYDPnQCbBI4+ouu9dm6mR4Iam43T4uCK
oiYAn3LBo7DhsCA7yAOiklyMBzrMbpJe
=8+Ep
-----END PGP SIGNATURE-----




reply via email to

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