Date: Sat, 31 Jan 2015 00:12:25 +0000 From: bugzilla-noreply@freebsd.org To: freebsd-bugs@FreeBSD.org Subject: [Bug 197216] incorrect signal delivery for linux apps Message-ID: <bug-197216-8@https.bugs.freebsd.org/bugzilla/>
next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=197216 Bug ID: 197216 Summary: incorrect signal delivery for linux apps Product: Base System Version: 11.0-CURRENT Hardware: Any OS: Any Status: New Severity: Affects Only Me Priority: --- Component: kern Assignee: freebsd-bugs@FreeBSD.org Reporter: henry.hu.sh@gmail.com FreeBSD's Linux emulation tries to translate between Linux signals and FreeBSD signals. However, this is not a one-to-one mapping, which results in some incorrect behavior. For example, if an application sets a signal handler for SIGPWR(30), and sends SIGPWR to itself, then the signal handler would be called, but the signal number passed in is not 30, but 23(SIGURG). The reason is that FreeBSD translates Linux's SIGPWR(30) to FreeBSD's SIGURG(16), but FreeBSD's SIGURG(16) is translated back to Linux's SIGURG(23). A simple test program: #include <signal.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> const int SIGNAL_TO_TEST = SIGPWR; void handler(int signum) { if (signum != SIGNAL_TO_TEST) { printf("Error! got signal %d expected %d\n", signum, SIGNAL_TO_TEST); } else { printf("Got signal %d as expected\n", signum); } } int main() { struct sigaction sigact; sigact.sa_handler = handler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; if (sigaction(SIGNAL_TO_TEST, &sigact, NULL) == -1) { perror("fail to call sigaction"); } kill(getpid(), SIGNAL_TO_TEST); sleep(1); } It should output Got signal 30 as expected but on FreeBSD it says Error! got signal 23 expected 30 instead. A real example can be found at https://github.com/mono/mono/blob/master/libgc/pthread_stop_world.c where it uses SIG_SUSPEND to pause threads. SIG_SUSPEND is defined to be SIGPWR. The signal handler checks the value of signal passed in: if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler"); A reasonable fix would be mapping SIGPWR to some currently unmapped FreeBSD signal, like SIGEMT. Although it's not completely correct in semantics, at least it works for signal delivery between Linux applications. For the uncommon signals like SIGURG and SIGPWR, usually they are not sent between FreeBSD and Linux applications. I think that we'd better keep them working as expected when being sent between Linux applications. -- You are receiving this mail because: You are the assignee for the bug.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-197216-8>