Hi,

I found the following two changes in POSIX 2024 that were not very well
documented in the CHANGE HISTORY section of <unistd.h> [1] [2]:

    The <unistd.h> header shall define the symbolic constants O_CLOEXEC
    and O_CLOFORK as described in <fcntl.h>.

    Inclusion of the <unistd.h> header may make visible all symbols from
    the headers <fcntl.h>, ...

This makes sense due to the addition of dup3 and pipe2. But most
systems, including glibc, require the inclusion of fcntl.h for these
flags [3].

I have applied the following two patches to define O_CLOEXEC in unistd.h
and add a test for it. I also documented the platforms that don't behave
like POSIX 2024 using the GitHub CI.

For now, I have ignored O_CLOFORK since I am unsure how many platforms
support it and Gnulib has no workaround for it, unlike O_CLOEXEC.

Collin

[1] https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/unistd.h.html
[2] https://austingroupbugs.net/view.php?id=1906
[3] https://sourceware.org/bugzilla/show_bug.cgi?id=32706

>From 10331a8ba5e9548671907a09eb6d5d7260543c39 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Sun, 16 Feb 2025 12:23:57 -0800
Subject: [PATCH 1/2] unistd-h: Make sure O_CLOEXEC is defined.

* modules/unistd-h (Depends-on): Add fcntl-h.
* lib/unistd.in.h: Include fcntl.h if inclusion of unistd.h does not
define O_CLOEXEC.
* doc/posix-headers/unistd.texi: Document the platforms that do not
define O_CLOEXEC in unistd.h.
---
 ChangeLog                     | 9 +++++++++
 doc/posix-headers/unistd.texi | 3 +++
 lib/unistd.in.h               | 9 ++++++---
 modules/unistd-h              | 1 +
 4 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1fa41775dc..de21277abe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2025-02-16  Collin Funk  <collin.fu...@gmail.com>
+
+	unistd-h: Make sure O_CLOEXEC is defined.
+	* modules/unistd-h (Depends-on): Add fcntl-h.
+	* lib/unistd.in.h: Include fcntl.h if inclusion of unistd.h does not
+	define O_CLOEXEC.
+	* doc/posix-headers/unistd.texi: Document the platforms that do not
+	define O_CLOEXEC in unistd.h.
+
 2025-02-16  Bruno Haible  <br...@clisp.org>
 
 	strncasecmp: Add tests.
diff --git a/doc/posix-headers/unistd.texi b/doc/posix-headers/unistd.texi
index 70c9a87154..4481bcfc1a 100644
--- a/doc/posix-headers/unistd.texi
+++ b/doc/posix-headers/unistd.texi
@@ -23,6 +23,9 @@ @node unistd.h
 @item
 The @code{_exit} function is not declared in this file on some platforms:
 mingw.
+@item
+This header file does not define @code{O_CLOEXEC} on some platforms:
+glibc 2.41, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Solaris 11.4, Cygwin 3.5, mingw, MSVC 14.
 
 @item
 Some platforms provide a @code{NULL} macro that cannot be used in arbitrary
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 3f96e10d7e..acabdf8c68 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -95,12 +95,15 @@
 # include <stdio.h>
 #endif
 
+/* FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Solaris 11.4, and glibc 2.41
+   do not define O_CLOEXEC in <unistd.h>.  */
 /* Cygwin 1.7.1 and Android 4.3 declare unlinkat in <fcntl.h>, not in
    <unistd.h>.  */
 /* But avoid namespace pollution on glibc systems.  */
-#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) \
-    && (defined __CYGWIN__ || defined __ANDROID__) \
-    && ! defined __GLIBC__
+#if ! defined O_CLOEXEC \
+    || ((@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) \
+         && (defined __CYGWIN__ || defined __ANDROID__) \
+         && ! defined __GLIBC__)
 # include <fcntl.h>
 #endif
 
diff --git a/modules/unistd-h b/modules/unistd-h
index af7fda5944..1a7376efdb 100644
--- a/modules/unistd-h
+++ b/modules/unistd-h
@@ -15,6 +15,7 @@ include_next
 snippet/arg-nonnull
 snippet/c++defs
 snippet/warn-on-use
+fcntl-h
 ssize_t
 stddef-h
 sys_types-h
-- 
2.48.1

>From 3b564fec28458688de4337ee5627568ce4dc78b9 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Sun, 16 Feb 2025 12:29:36 -0800
Subject: [PATCH 2/2] unistd-h tests: Check that unistd.h defines O_CLOEXEC.

* tests/test-unistd-h.c: Prefer #error to emitting a syntax error. Check
that O_CLOEXEC is defined.
---
 ChangeLog             | 4 ++++
 tests/test-unistd-h.c | 6 +++++-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index de21277abe..ba22c1571a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2025-02-16  Collin Funk  <collin.fu...@gmail.com>
 
+	unistd-h tests: Check that unistd.h defines O_CLOEXEC.
+	* tests/test-unistd-h.c: Prefer #error to emitting a syntax error. Check
+	that O_CLOEXEC is defined.
+
 	unistd-h: Make sure O_CLOEXEC is defined.
 	* modules/unistd-h (Depends-on): Add fcntl-h.
 	* lib/unistd.in.h: Include fcntl.h if inclusion of unistd.h does not
diff --git a/tests/test-unistd-h.c b/tests/test-unistd-h.c
index d7173956df..fa86969583 100644
--- a/tests/test-unistd-h.c
+++ b/tests/test-unistd-h.c
@@ -30,7 +30,11 @@ int sk[] = { SEEK_CUR, SEEK_END, SEEK_SET };
 /* Check that the various *_FILENO macros are defined.  */
 #if ! (defined STDIN_FILENO                                     \
        && (STDIN_FILENO + STDOUT_FILENO + STDERR_FILENO == 3))
-missing or broken *_FILENO macros
+# error "missing or broken *_FILENO macros"
+#endif
+
+#ifndef O_CLOEXEC
+# error "O_CLOEXEC is not defined"
 #endif
 
 /* Check that the types are all defined.  */
-- 
2.48.1

Reply via email to