headers: give timerfd/signalfd prototypes C linkage
sys/timerfd.h and sys/signalfd.h declare their functions in the cbindgen
`trailer`, which is emitted after the include guard closes and OUTSIDE the
extern "C" block that cpp_compat=true generates. The prototypes therefore took
C++ linkage, so a C++ consumer asked the linker for a mangled symbol while
relibc exports the plain C one:
alignedtimer.cpp:(.text+0x29a): undefined reference to
`timerfd_create(int, int)'
(plasma-workspace libclock). C callers were unaffected, which is why this
survived until a C++ consumer appeared.
The prototypes are hand-written rather than generated on purpose: cbindgen
renders them with a bare `itimerspec` and a `clockid_t` parameter, which does
not resolve in a plain C99 include and previously broke libwayland's
TFD_CLOEXEC probe. That stays; only the linkage is corrected.
signalfd has no in-tree C++ consumer yet and is fixed pre-emptively.
This commit is contained in:
@@ -9,8 +9,24 @@ trailer = """
|
||||
#define SFD_NONBLOCK 0x800
|
||||
#endif
|
||||
|
||||
/* extern "C" is REQUIRED here; cpp_compat only wraps cbindgen's GENERATED
|
||||
* body, and this trailer is emitted outside it. Without this a C++ consumer
|
||||
* links against the mangled name while relibc exports the plain C symbol.
|
||||
* Same defect as sys_timerfd, which surfaced as
|
||||
* undefined reference to `timerfd_create(int, int)'
|
||||
* once plasma-workspace (C++) used it. Fixed here pre-emptively: no in-tree
|
||||
* C++ consumer of signalfd exists yet, so this is latent rather than observed.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int signalfd(int fd, const sigset_t *mask, size_t masksize);
|
||||
int signalfd4(int fd, const sigset_t *mask, size_t masksize, int flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
"""
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
@@ -25,9 +25,30 @@ trailer = """
|
||||
#define TFD_TIMER_CANCEL_ON_SET 0x2
|
||||
#endif
|
||||
|
||||
/* extern "C" is REQUIRED here and cannot be left to cpp_compat.
|
||||
*
|
||||
* cpp_compat=true wraps only the body cbindgen GENERATES. These three
|
||||
* prototypes are hand-written in this trailer (see the [export] note below),
|
||||
* and the trailer is emitted after the include guard closes, outside that
|
||||
* wrapper. Without an explicit extern "C" they take C++ linkage, so a C++
|
||||
* consumer asks the linker for the mangled name while relibc exports the plain
|
||||
* C symbol:
|
||||
* alignedtimer.cpp:(.text+0x29a): undefined reference to
|
||||
* `timerfd_create(int, int)'
|
||||
* (first hit: plasma-workspace libclock/alignedtimer.cpp). C callers were
|
||||
* unaffected, which is why this survived until a C++ consumer appeared.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int timerfd_create(int clockid, int flags);
|
||||
int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
|
||||
int timerfd_gettime(int fd, struct itimerspec *curr_value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
"""
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
Reference in New Issue
Block a user