Commitf795d54591("libc,shared: detect newer library symbols at runtime") replaced the build-time HAVE_EPOLL_PWAIT2 gate with a runtime shim that resolves the libc symbol via dlsym(RTLD_DEFAULT, "epoll_pwait2"). That breaks on 32-bit architectures built with _TIME_BITS=64 (e.g. Debian armhf since the time64 transition). When _TIME_BITS=64 is in effect on a 32-bit target, glibc's <sys/epoll.h> asm-renames the C identifier `epoll_pwait2` to the matching 64-bit-time_t ABI symbol `__epoll_pwait2_time64`, so a normal C call resolves to the variant whose `struct timespec` layout (16 bytes: s64 tv_sec, long tv_nsec, long pad) matches what the compiler is using: /* /usr/include/sys/epoll.h */ #ifndef __USE_TIME64_REDIRECTS extern int epoll_pwait2 (int __epfd, struct epoll_event *__events, int __maxevents, const struct timespec *__timeout, const __sigset_t *__ss) ...; #else # ifdef __REDIRECT extern int __REDIRECT (epoll_pwait2, (int __epfd, ..., const struct timespec *__timeout, const __sigset_t *__ss), __epoll_pwait2_time64) ...; # else # define epoll_pwait2 __epoll_pwait2_time64 # endif #endif dlsym() doesn't see that header-level rename and returns the legacy 32-bit-time_t `epoll_pwait2` symbol, which interprets only the first 8 bytes of the 16-byte timespec we hand it. With a little-endian layout that means the legacy callee reads tv_sec = (low 32 bits of real tv_sec) and tv_nsec = (high 32 bits of real tv_sec, normally 0). Sub-second timeouts therefore become {0,0} and return immediately, while multi- second timeouts get truncated to whole seconds. That matches the test failure reported on armv7: /* test_simple_timeout */ src/libsystemd/sd-event/test-event.c:724: Assertion failed: Expected "t >= usec_add(f, some_time)", but 571153514285 < 571154403965 (the 889680 us shortfall is consistent with a sub-second `some_time` that got rounded down to zero by the truncated wait). Fix it by adding a DEFINE_LIBC_ERRNO_SHIM_NAMED() variant of the macro that takes an explicit dlsym symbol name string. Both macros keep their own copy of the body so every `func` reference stays behind `#` or `##`, otherwise the override-header `#define epoll_pwait2 epoll_pwait2_shim` would rewrite the token before the inner macro could paste it (yielding `epoll_pwait2_shim_shim`). src/libc/epoll.c then picks "__epoll_pwait2_time64" under __USE_TIME_BITS64 so the cached function pointer matches the timespec ABI the rest of the code is built with. Follow-up forf795d54591Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
System and Service Manager
Details
Most documentation is available on systemd's web site.
Assorted, older, general information about systemd can be found in the systemd Wiki.
Information about build requirements is provided in the README file.
Consult our NEWS file for information about what's new in the most recent systemd versions.
Please see the Code Map for information about this repository's layout and content.
Please see the Hacking guide for information on how to hack on systemd and test your modifications.
Please see our Contribution Guidelines for more information about filing GitHub Issues and posting GitHub Pull Requests.
When preparing patches for systemd, please follow our Coding Style Guidelines.
If you are looking for support, please contact our mailing list, join our IRC channel #systemd on libera.chat or Matrix channel
Stable branches with backported patches are available in the stable repo.
We have a security bug bounty program sponsored by the Sovereign Tech Fund hosted on YesWeHack
Repositories with distribution packages built from git main are available on OBS, and also repositories with packages built from the latest stable release
