Geoff Clare via austin-group-l at The Open Group wrote in <aRWtddaFf8b5GbBx@localhost>: |Steffen Nurpmeso wrote, on 11 Nov 2025: |> |>|| The safe counterpart for avoiding the same race with dup( ) is |>|| the use of the F_DUPFD_CLOFORK or F_DUPFD_CLOEXEC action of the |>|| fcntl( ) function. |> |> sounds definitive, whereas i stood in dead-end when coding. | |The APPLICATION USAGE for fcntl() says: | | In order to set both FD_CLOEXEC and FD_CLOFORK when duplicating a | file descriptor, applications should use F_DUPFD_CLOFORK to obtain | the new file descriptor with FD_CLOFORK already set, and then use | F_SETFD to set the FD_CLOEXEC flag on the new descriptor. (The | alternative of first using F_DUPFD_CLOEXEC and then setting | FD_CLOFORK with F_SETFD has a timing window where another thread | could create a child process which inherits the new descriptor | because FD_CLOFORK has not yet been set.) | |The only loophole I can see in that method is that in between the two |fcntl() calls the fd would be leaked if the current process calls
Three. Should be three says POSIX Applications using these functions should do a read-modify-write operation on them, rather than assuming that only the values defined by this volume of POSIX.1-2024 are valid. It is a common error to forget this, and to mention that my memory rings as not too far back, i think, yes, on OpenBSD, after CLOFORK support came, software had to be a.k.a. was adjusted accordingly. (Not to mention certain super popular shells. Sure they do not use CLOFORK yet, but people look, and people learn, and people replicate. For example $ git grep ETFD master master:src/redir.c: fcntl(newfd, F_SETFD, FD_CLOEXEC); Popular and world-wide-known "hacker" in kernel sphere. And then application usage is informative only, too.) |exec, but that is an extremely unlikely thing for the process to do |(i.e. call exec in one thread while other threads are actively running). (Hm since other threads "are simply destroyed" i do not know; i personally always hated that Butenhof approach, i would have added an explicit posix_enable_threads(ptf) before threads were possible, where that ptf would continue execution in a thread environment. And main thread / worker thread. That would have been simpler, especially with all the signal stuff. I said here to Butenhof over ten years ago i think, having had seen Linuxthreads implementation around Y2K. But that ship has sailed so long ago, ISO C is even more simplicistic, and what do i know in the end and at all.) |If it does ever happen, it would be because the application has a bug |in its thread coordination. Three system calls to get that "atomic" thing done, now i really shiver. The I/O layer lock layers, the system call overhead, the side-channel mitigation caused extra flushes (on this box ~40+ percent kernel compilation time increasement, 6.1 series), the additional scheduler checks to end my time slice. Three!? And what about possible signal blocks to avoid longjmp()s away in a signal driven environment, or user level tracking of used file descriptors (needs thread locks aka likely mutexes; or atomically setting a pointer in a pre-prepared list node, for example; ok, POSIX now has stdatomic). You cannot write a safe library function that creates a duplicated descriptor with both CLOFORK and CLOEXEC set. Unless you say the user has to block signals around the function call in a jumping environment, and the user is likewise responsible for tracking the file descriptor -- or how many mutexes do you want, of how many descriptor tracking (thinking of FDs in certain states, to diversify it) lists, vectors, maps or trees or etc? And holding a mutex over three successive (now exaggerating) system calls seems no good in a heavily multithreaded environment (for tracking FDs). But then, CLOFORK is a dedicated thing, and will surely be used only in code which has specific needs, and can thus likely be adopted easily. --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt)
