From: Sören Tempel <soe...@soeren-tempel.net> Tested on x86_64 Arch Linux (glibc) and Alpine Linux (musl libc).
Previously, libgo relied on the _sigev_un implementation-specific field in struct sigevent, which is only available on glibc. This patch uses the sigev_notify_thread_id macro instead which is mandated by timer_create(2). In theory, this should work with any libc implementation for Linux. Unfortunately, there is an open glibc bug as glibc does not define this macro. For this reason, a glibc-specific workaround is required. Other libcs (such as musl) define the macro and don't require the workaround. This makes go_signal compatible with musl libc. See: https://sourceware.org/bugzilla/show_bug.cgi?id=27417 Signed-off-by: Sören Tempel <soe...@soeren-tempel.net> --- Changes since v1: Add workaround for glibc. libgo/go/runtime/os_linux.go | 4 +++- libgo/runtime/go-signal.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go index 96fb1788..6653d85e 100644 --- a/libgo/go/runtime/os_linux.go +++ b/libgo/go/runtime/os_linux.go @@ -22,6 +22,8 @@ type mOS struct { profileTimerValid uint32 } +func setProcID(uintptr, int32) + func getProcID() uint64 { return uint64(gettid()) } @@ -365,7 +367,7 @@ func setThreadCPUProfiler(hz int32) { var sevp _sigevent sevp.sigev_notify = _SIGEV_THREAD_ID sevp.sigev_signo = _SIGPROF - *((*int32)(unsafe.Pointer(&sevp._sigev_un))) = int32(mp.procid) + setProcID(uintptr(unsafe.Pointer(&sevp)), int32(mp.procid)) ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, &sevp, &timerid) if ret != 0 { // If we cannot create a timer for this M, leave profileTimerValid false diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c index 528d9b6d..c56350cc 100644 --- a/libgo/runtime/go-signal.c +++ b/libgo/runtime/go-signal.c @@ -16,6 +16,11 @@ #define SA_RESTART 0 #endif +// Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=27417 +#if __linux__ && !defined(sigev_notify_thread_id) + #define sigev_notify_thread_id _sigev_un._tid +#endif + #ifdef USING_SPLIT_STACK extern void __splitstack_getcontext(void *context[10]); @@ -183,6 +188,16 @@ setSigactionHandler(struct sigaction* sa, uintptr handler) sa->sa_sigaction = (void*)(handler); } +void setProcID(uintptr_t, int32_t) + __asm__ (GOSYM_PREFIX "runtime.setProcID"); + +void +setProcID(uintptr_t ptr, int32_t v) +{ + struct sigevent *s = (void *)ptr; + s->sigev_notify_thread_id = v; +} + // C code to fetch values from the siginfo_t and ucontext_t pointers // passed to a signal handler.