Skip to content

Comments

Fix sem_clockwait detection for cross-compiled builds#985

Open
andiradulescu wants to merge 3 commits intoastral-sh:mainfrom
andiradulescu:fix-sem-clockwait-weak-symbol
Open

Fix sem_clockwait detection for cross-compiled builds#985
andiradulescu wants to merge 3 commits intoastral-sh:mainfrom
andiradulescu:fix-sem-clockwait-weak-symbol

Conversation

@andiradulescu
Copy link

@andiradulescu andiradulescu commented Feb 22, 2026

When cross-compiling against old glibc headers (e.g., Debian Stretch's glibc 2.24), configure cannot detect sem_clockwait (added in glibc 2.30). This causes CPython to fall back to sem_timedwait with CLOCK_REALTIME, making threading.Event.wait() hang indefinitely when the system clock jumps backward (e.g., NTP sync).

This PR adds patches that declare sem_clockwait as a weak symbol on Linux when configure doesn't detect it. At runtime, the weak symbol resolves to the real function on glibc 2.30+ or to NULL on older glibc. The patched code checks this at runtime and falls back to sem_timedwait gracefully.

Version-specific patches for CPython 3.10, 3.11, 3.12, 3.13+ (including 3.14) and 3.15 (currently in alpha) account for differences in the threading internals across versions.

The issue was first discovered in commaai/openpilot#33993 (comment)

Test results

All patches verified by building on Debian Stretch (glibc 2.24, where sem_clockwait doesn't exist in headers) and running on Debian Bookworm (glibc 2.36):

Python Build glibc Runtime glibc Weak symbol resolves Event.wait(0.1)
3.10.19 2.24 (Stretch) 2.36 (Bookworm) real function 0.101s
3.11.14 2.24 (Stretch) 2.36 (Bookworm) real function 0.103s
3.12.12 2.24 (Stretch) 2.36 (Bookworm) real function 0.103s
3.13.12 2.24 (Stretch) 2.36 (Bookworm) real function 0.102s
3.14.3 2.24 (Stretch) 2.36 (Bookworm) real function 0.102s
3.15.0a6 2.24 (Stretch) 2.36 (Bookworm) real function 0.101s
3.12.12 2.24 (Stretch) 2.24 (Stretch) NULL → sem_timedwait fallback 0.101s

test-sem-clockwait.py

When cross-compiling against old glibc headers (e.g., Debian Stretch's
glibc 2.24), configure cannot detect sem_clockwait (added in glibc 2.30).
This causes CPython to fall back to sem_timedwait with CLOCK_REALTIME,
making threading.Event.wait() hang indefinitely when the system clock
jumps backward (e.g., NTP sync).

Add patches that declare sem_clockwait as a weak symbol on Linux when
configure didn't detect it. At runtime, the weak symbol resolves to the
real function on glibc 2.30+ or to NULL on older glibc. The patched code
checks this at runtime and falls back to sem_timedwait gracefully.

Version-specific patches for CPython 3.10, 3.11, 3.12, and 3.13+ account
for differences in the threading internals across versions.
@andiradulescu andiradulescu marked this pull request as ready for review February 22, 2026 22:16
@jjhelmus
Copy link
Contributor

Looks like the patch needs to be modified to apply cleanly on 3.15 (currently in alpha).

@andiradulescu andiradulescu force-pushed the fix-sem-clockwait-weak-symbol branch from a688da3 to 8ac6af1 Compare February 23, 2026 17:59
In 3.15, the semaphore lock code moved from thread_pthread.h to
parking_lot.c.
@andiradulescu andiradulescu force-pushed the fix-sem-clockwait-weak-symbol branch from 8ac6af1 to 4f545d7 Compare February 23, 2026 18:02
@andiradulescu
Copy link
Author

Added the 3.15 patch. The 3.15 one is simpler than the others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants