standards/169962: fcntl() to support F_DUPFD_CLOEXEC specified in
POSIX.1-2008
Jukka Ukkonen
jau at iki.fi
Wed Jul 18 08:50:11 UTC 2012
>Number: 169962
>Category: standards
>Synopsis: fcntl() to support F_DUPFD_CLOEXEC specified in POSIX.1-2008
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-standards
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Jul 18 08:50:11 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator: Jukka Ukkonen
>Release: FreeBSD 9.1-PRERELEASE
>Organization:
-----
>Environment:
FreeBSD sleipnir 9.1-PRERELEASE FreeBSD 9.1-PRERELEASE #0: Wed Jul 18 10:49:35 EEST 2012 root at sleipnir:/usr/obj/usr/src/sys/Sleipnir amd64
>Description:
The attached patch adds the flag F_DUPFD_CLOEXEC to fcntl() to allow duplication
of file descriptors such that FD_CLOEXEC will be automatically and atomically set
for the new fd.
While in the process of adding F_DUPFD_CLOEXEC which is required by POSIX.1-2008
I also added F_DUP2FD_CLOEXEC for symmetry and analogy with F_DUPFD<->F_DUP2FD.
>How-To-Repeat:
See full description above.
>Fix:
Find a patch attached.
Patch attached with submission follows:
--- sys/sys/fcntl.h.orig 2012-07-18 10:37:07.000000000 +0300
+++ sys/sys/fcntl.h 2012-07-18 10:42:27.000000000 +0300
@@ -225,6 +225,8 @@
#define F_SETLK_REMOTE 14 /* debugging support for remote locks */
#define F_READAHEAD 15 /* read ahead */
#define F_RDAHEAD 16 /* Darwin compatible read ahead */
+#define F_DUPFD_CLOEXEC 17 /* POSIX.1-2008 */
+#define F_DUP2FD_CLOEXEC 18 /* Symmetry DUPFD<->DUP2FD */
/* file descriptor flags (F_GETFD, F_SETFD) */
#define FD_CLOEXEC 1 /* close-on-exec flag */
--- sys/kern/kern_descrip.c.orig 2012-07-18 10:33:57.000000000 +0300
+++ sys/kern/kern_descrip.c 2012-07-18 10:34:45.000000000 +0300
@@ -113,6 +113,7 @@
/* Flags for do_dup() */
#define DUP_FIXED 0x1 /* Force fixed allocation */
#define DUP_FCNTL 0x2 /* fcntl()-style errors */
+#define DUP_CLOEXEC 0x4 /* Atomically set FD_CLOEXEC. */
static int do_dup(struct thread *td, int flags, int old, int new,
register_t *retval);
@@ -490,6 +491,18 @@
error = do_dup(td, DUP_FIXED, fd, tmp, td->td_retval);
break;
+ case F_DUPFD_CLOEXEC:
+ tmp = arg;
+ error = do_dup(td, (DUP_FCNTL|DUP_CLOEXEC),
+ fd, tmp, td->td_retval);
+ break;
+
+ case F_DUP2FD_CLOEXEC:
+ tmp = arg;
+ error = do_dup(td, (DUP_FIXED|DUP_CLOEXEC),
+ fd, tmp, td->td_retval);
+ break;
+
case F_GETFD:
FILEDESC_SLOCK(fdp);
if ((fp = fdtofp(fd, fdp)) == NULL) {
@@ -826,6 +839,19 @@
}
if (flags & DUP_FIXED && old == new) {
*retval = new;
+
+ /*
+ * NOTICE! - We err on the safe side.
+ * The principle is least surprise, least confusion.
+ * If we dup the fd to itself explicitly requesting CLOEXEC,
+ * the flag shall be added.
+ * If there is no explicit request to set CLOEXEC but
+ * the fd already had it set, we shall not touch it.
+ */
+
+ if (flags & DUP_CLOEXEC)
+ fdp->fd_ofileflags[new] |= UF_EXCLOSE;
+
FILEDESC_XUNLOCK(fdp);
return (0);
}
@@ -911,7 +937,12 @@
* Duplicate the source descriptor
*/
fdp->fd_ofiles[new] = fp;
- fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
+
+ if (flags & DUP_CLOEXEC)
+ fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] | UF_EXCLOSE;
+ else
+ fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
+
if (new > fdp->fd_lastfile)
fdp->fd_lastfile = new;
*retval = new;
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-standards
mailing list