Repository navigation
Description
hi again, I have some more super fun things to report
as a short preamble, fixing the missing constants seems to be mostly just a continuation of the work in #193 also i apologize if this should really be multiple issues, I did it all in one bc I thought it would've felt needlessly spammy since the majority of the work here is more or less the same thing even if concerns different upstream files. also same as before I'm just reporting this here bc the most immediate issues is (aside from the generally missing RDS_* macros) for y'all. I also wrote some patches just to examine ig if it rly is just continuing the existing work and it unsurprisingly does seem to be, the same nuances apply for avoiding header clashes but aside from that seems to be all the same thing more or less.
The tldr is in terms of missing constants is as follows
#ifdef const: exported under#ifdef NAME, so the build's libc headers must define the name.#ifdef group (X): exported without its own guard, inside a block guarded byX, so it is missing becauseXis.glibc include: the header CPython takes it from only exists in newer glibc, so the include itself is skipped.#ifdef const (argument): an argument that raisesNotImplementedErrorunless its C macro is defined.configure link test: an argument that needs a glibc wrapper function, detected by linking at configure time.
Process and timers (os)
| Constant | glibc | Why missing | Notes |
|---|---|---|---|
POSIX_SPAWN_SETSID |
2.26 | #ifdef const (argument) |
Not exported. os.posix_spawn(setsid=True) raises NotImplementedError (posixmodule.c:7658-7677), as documented in os.rst:5436-5439. With the macro defined, a runtime glibc older than 2.26 gives OSError(EINVAL) instead. |
PIDFD_NONBLOCK |
2.36 | glibc include |
Taken from <sys/pidfd.h> (HAVE_SYS_PIDFD_H, posixmodule.c:64-66), then #ifdef at posixmodule.c:18470. #127583 / #127593 fixed it for glibc 2.36+ only; RHEL 9 and Ubuntu 22.04 builds still lack it. Docs promise "Linux >= 5.10". Value is O_NONBLOCK. |
TFD_TIMER_CANCEL_ON_SET |
2.26 | #ifdef const |
posixmodule.c:18438. <sys/timerfd.h> itself is old (glibc 2.8); only the constant is new. |
Vectored I/O flags (os.preadv / os.pwritev)
| Constant | glibc | Why missing | Notes |
|---|---|---|---|
flags= argument |
2.26 | configure link test |
HAVE_PREADV2 / HAVE_PWRITEV2 link preadv2()/pwritev2(); without them any non-zero flags raises NotImplementedError (posixmodule.c:12418-12423, 13124-13129). Docs promise "Linux >= 4.6". The syscalls need no glibc support, as for copy_file_range in #155520. |
RWF_DSYNC |
2.26 | #ifdef const |
posixmodule.c:18516. Docs promise "Linux >= 4.7". |
RWF_HIPRI |
2.26 | #ifdef const |
#13980 made test_posix skip when the constant exists but preadv2 does not; that skip is why CI never saw the missing flags. |
RWF_SYNC |
2.26 | #ifdef const |
test_pwritev_flags is gated on it but has never run. |
RWF_NOWAIT |
2.26 | #ifdef const |
|
RWF_APPEND |
2.28 | #ifdef const |
Added after the abandoned #13735. |
RWF_ATOMIC |
2.41 | #ifdef const |
Missing from any build on glibc < 2.41 (Ubuntu 24.04, Debian 12), not only pbs. |
Later flags (#139090 RWF_DONTCACHE, #153856 RWF_NOSIGNAL) will follow the same pattern: posixmodule does not include <linux/fs.h>, so they only appear once glibc's headers have them.
Clocks, polling and memory (time, select, mmap)
| Constant | glibc | Why missing | Notes |
|---|---|---|---|
CLOCK_TAI |
2.21 | #ifdef const |
timemodule.c:2134. Added in #19096. CentOS 7's backported "2.17" has it. |
EPOLLEXCLUSIVE |
2.24 | #ifdef const |
selectmodule.c:2774. #89114 (open) asks for it in selectors. |
MADV_FREE |
2.24 | #ifdef const |
mmapmodule.c:2394. <linux/mman.h> can be included alongside the libc headers. |
File locks and descriptors (fcntl)
| Constant | glibc | Why missing | Notes |
|---|---|---|---|
F_OFD_GETLK |
2.20 | #ifdef const |
fcntlmodule.c:600-608. Docs: "On Linux(>=3.15) ... exposes F_OFD_GETLK". hasattr checks for it fall back to process-associated locks. CentOS 7's "2.17" has it. |
F_OFD_SETLK |
2.20 | #ifdef const |
As F_OFD_GETLK. The integer value works on a pbs build (repro). |
F_OFD_SETLKW |
2.20 | #ifdef const |
As F_OFD_GETLK. |
F_DUPFD_QUERY |
2.41 | #ifdef const |
fcntlmodule.c:656. Missing from any build on glibc < 2.41, not only pbs. |
File sealing (fcntl)
| Constant | glibc | Why missing | Notes |
|---|---|---|---|
F_ADD_SEALS |
2.27 | #ifdef const |
fcntlmodule.c:817-828 guards the whole group. Sealing is for memfd_create(), which pbs does provide (through its patch), so the function is there and its constants are not. |
F_GET_SEALS |
2.27 | #ifdef group (F_ADD_SEALS) |
|
F_SEAL_SEAL |
2.27 | #ifdef group (F_ADD_SEALS) |
|
F_SEAL_SHRINK |
2.27 | #ifdef group (F_ADD_SEALS) |
|
F_SEAL_GROW |
2.27 | #ifdef group (F_ADD_SEALS) |
|
F_SEAL_WRITE |
2.27 | #ifdef group (F_ADD_SEALS) |
|
F_SEAL_FUTURE_WRITE |
2.30 | #ifdef const, inside #ifdef group (F_ADD_SEALS) |
fcntlmodule.c:825. Added in #114061. |
Write-life hints (fcntl)
| Constant | glibc | Why missing | Notes |
|---|---|---|---|
F_GET_RW_HINT |
2.27 | #ifdef const |
fcntlmodule.c:693-708 guards the whole group. |
F_SET_RW_HINT |
2.27 | #ifdef group (F_GET_RW_HINT) |
|
F_GET_FILE_RW_HINT |
2.27 | #ifdef group (F_GET_RW_HINT) |
Still in the headers, but the kernel rejects it (EINVAL on 7.2.3). |
F_SET_FILE_RW_HINT |
2.27 | #ifdef group (F_GET_RW_HINT) |
As F_GET_FILE_RW_HINT. |
RWH_WRITE_LIFE_NOT_SET |
2.32 | #ifdef group (F_GET_RW_HINT) |
glibc 2.27-2.31 only have the kernel's misspelling RWF_WRITE_LIFE_NOT_SET, which CPython maps (fcntlmodule.c:699-701), so in practice it is exported from 2.27. |
RWH_WRITE_LIFE_NONE |
2.27 | #ifdef group (F_GET_RW_HINT) |
|
RWH_WRITE_LIFE_SHORT |
2.27 | #ifdef group (F_GET_RW_HINT) |
|
RWH_WRITE_LIFE_MEDIUM |
2.27 | #ifdef group (F_GET_RW_HINT) |
|
RWH_WRITE_LIFE_LONG |
2.27 | #ifdef group (F_GET_RW_HINT) |
|
RWH_WRITE_LIFE_EXTREME |
2.27 | #ifdef group (F_GET_RW_HINT) |
TCP options (socket)
All are guarded one by one in socketmodule.c:9155-9193 and come from glibc's <netinet/tcp.h>; <linux/tcp.h> cannot be included next to it.
| Constant | glibc | Why missing | Notes |
|---|---|---|---|
TCP_NOTSENT_LOWAT |
2.23 | #ifdef const |
The integer value works on a pbs build (repro). #19402 tried a hardcoded fallback for the same gap in macOS builds; closed without review. |
TCP_CC_INFO |
2.23 | #ifdef const |
|
TCP_SAVE_SYN |
2.23 | #ifdef const |
|
TCP_SAVED_SYN |
2.23 | #ifdef const |
|
TCP_REPAIR_WINDOW |
2.25 | #ifdef const |
|
TCP_FASTOPEN_CONNECT |
2.26 | #ifdef const |
|
TCP_ULP |
2.27 | #ifdef const |
|
TCP_MD5SIG_EXT |
2.27 | #ifdef const |
|
TCP_FASTOPEN_KEY |
2.28 | #ifdef const |
|
TCP_FASTOPEN_NO_COOKIE |
2.28 | #ifdef const |
|
TCP_ZEROCOPY_RECEIVE |
2.29 | #ifdef const |
|
TCP_INQ |
2.29 | #ifdef const |
|
TCP_TX_DELAY |
2.31 | #ifdef const |
Protocols, address families and socket levels (socket)
| Constant | glibc | Why missing | Notes |
|---|---|---|---|
IPPROTO_MPTCP |
2.32 | #ifdef const |
socketmodule.c:8820. Added in #24946. The integer value works on a pbs build (repro). <linux/in.h> can be included. |
SOL_RDS |
2.24 | #ifdef const |
socketmodule.c:8678. <linux/rds.h> can be included. |
AF_QIPCRTR |
2.25 | #ifdef const |
socketmodule.c:7896. Also needs <linux/qrtr.h>: without it socketmodule.h #undefs the name (socketmodule.h:114-121). Added in #3706. |
Missing functions
preadv()/pwritev() refuse any non-zero flags #ifndef HAVE_PREADV2 / HAVE_PWRITEV2 (posixmodule.c:12418-12423, 13124-13129) through argument_unavailable_error(). HAVE_PREADV2 is configure's link test for the glibc 2.26 wrapper, which a 2.19 sysroot fails. Here the existing syscall fallback strat should work. i.e. just
#if defined(HAVE_PREADV2) || (defined(__linux__) && defined(__NR_preadv2))
# define _Py_HAVE_PREADV2
#endif
#if defined(HAVE_PWRITEV2) || (defined(__linux__) && defined(__NR_pwritev2))
# define _Py_HAVE_PWRITEV2
#endif
#ifdef __linux__
// Mirroring `LO_HI_LONG(val)` from (sysdeps/unix/sysv/linux/sysdep.h:93-95)
# define _Py_LO_HI_LONG(off) (long)(off), (long)((uint64_t)(off) >> 32)
#endifand then at the HAVE_{PREADV2/PWRITEV2} sites the approaches reduces to just
#ifndef _Py_HAVE_*V2
// arg unavail error for nonzero flags
#else
#ifdef _Py_HAVE_*V2
// syscall avail on non-zero flags, yippeee!
#endif
The usual point applies that these changes mean for older host libc's or kernels OSError's would be raised with these fixes applied.
Related upstream issues/notes
test_pwritev_flagshas never run: it is gated onhasattr(posix, 'os.RWF_SYNC'), always False since bpo-31368 (2018), bc it should be'RWF_SYNC'and its expected data is wrong (b'xxtest1tt2'instead ofb'xxtest1tt2t3'validated against just calling it directly).- I think it would make sense to probably add tests to CPython to assert that these macros are actually present i.e. the fallbacks correctly trigger when building against lacking libc, unsure if there is any prior instance of this kind of testing but I assume it might be nice even if it is basically just testing like basic preprocessor semantics. One example that motivates it would be the addition of PIDFD_NONBLOCK, was added in 2022 but nothing CPython included actually defined it so it was always just gone untill 2 years later the actual header file was added to make it work, I would assume had this been given like a presence check it would've raised the error.
- I was curious if the
PIDFD_NONBLOCKdefect ,i.e. the missing header for macro defs, appeared anywhere else and I found that the full RDS_* group here which comes from rds.h exhibits the same issue i.e. its missing rds.h, there's one related open issue based on what I can tell virtually nobody uses these constants hence why this has gone essentially unreported since they were added in 2011; turns out CPython does a namespace pollution lint test this might complicate adding the header, (could use__has_include(C23, alrdy used in some places) maybe?), but again low prio. There is alsoMADV_SOFT_OFFLINEdefined in<asm-generic/mman-common.h>atmmapmodule.c:2379-2381but header is missing.
Activity
zanieb commentedon Oct 27, 2026
Thanks for the comprehensive issue!