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.
Interesting. What happens if you pass the bit value of O_CLOEXEC to an
older kernel that doesn't understand it - does the open fail with ENOSYS,
or does it cause a kernel panic (requiring a reboot for recovery)?
Of course not a panic---they needed a reboot to get O_CLOEXEC to work
because it was requested in the executable but not supported in the
kernel. You get EINVAL, actually. accept4 and other new function calls
give ENOSYS instead.
Regarding the patch, I'll write and test one.
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".
We already have a cloexec module, which provides the utility wrapper
function set_cloexec_flag. But I could agree to making this module cover
all the magic that turns on cloexec support across the rest of gnulib.
We could actually obsolete cloexec when all the magic is in place.
Yes, but unlike dup2.c where we are emulating fcntl(n, F_DUPFD, 3), you
are now introducing an arbitrarily large target, such that your recursion
could now risk overflowing the stack. We'd probably have to rewrite it to
track dup allocation attempts using a heap struct if target is larger than
some minimum (or, is mingw subject to a compile-time maximum of open fds
where we can just return EMFILE up front?).
I think so (but it would be EBADF, no?)
Paolo