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.
The FreeBSD kernel supports signals 1..126. I think it would be acceptable to use some of the unused FreeBSD signal numbers for mapping Linux signals that FreeBSD does not have. Note that all the unused signals have default action terminate without core dump; this matches SIGPWR but may cause subtle breakage for signals that default to ignore in Linux.
agree with you, Jilles. i will fix this
A commit references this bug: Author: dchagin Date: Sat Feb 21 20:40:44 UTC 2015 New revision: 279107 URL: https://svnweb.freebsd.org/changeset/base/279107 Log: Rework signal code to allow using it by other modules, like linprocfs: 1. Linux sigset always 64 bit on all platforms. In order to move Linux sigset code to the linux_common module define it as 64 bit int. Move Linux sigset manipulation routines to the MI path. 2. Move Linux signal number definitions to the MI path. In geneeral they are the same on all platforms except for a few signals. 3. Map Linux RT signals to the FreeBSD RT signals and hide signal conversion tables to avoid conversion errors. 4. Emulate Linux SIGPWR signal via FreeBSD SIGRTMIN signal which is outside of allowed on Linux signal numbers. PR: 197216 Changes: user/dchagin/lemul/sys/amd64/linux/linux.h user/dchagin/lemul/sys/amd64/linux/linux_machdep.c user/dchagin/lemul/sys/amd64/linux/linux_sysvec.c user/dchagin/lemul/sys/amd64/linux32/linux.h user/dchagin/lemul/sys/amd64/linux32/linux32_machdep.c user/dchagin/lemul/sys/amd64/linux32/linux32_sysvec.c user/dchagin/lemul/sys/compat/linux/linux.c user/dchagin/lemul/sys/compat/linux/linux.h user/dchagin/lemul/sys/compat/linux/linux_fork.c user/dchagin/lemul/sys/compat/linux/linux_misc.c user/dchagin/lemul/sys/compat/linux/linux_signal.c user/dchagin/lemul/sys/compat/linux/linux_signal.h user/dchagin/lemul/sys/i386/linux/linux.h user/dchagin/lemul/sys/i386/linux/linux_sysvec.c user/dchagin/lemul/sys/modules/linux/Makefile user/dchagin/lemul/sys/modules/linux_common/Makefile
A commit references this bug: Author: dchagin Date: Sun May 24 17:47:24 UTC 2015 New revision: 283474 URL: https://svnweb.freebsd.org/changeset/base/283474 Log: Rework signal code to allow using it by other modules, like linprocfs: 1. Linux sigset always 64 bit on all platforms. In order to move Linux sigset code to the linux_common module define it as 64 bit int. Move Linux sigset manipulation routines to the MI path. 2. Move Linux signal number definitions to the MI path. In general, they are the same on all platforms except for a few signals. 3. Map Linux RT signals to the FreeBSD RT signals and hide signal conversion tables to avoid conversion errors. 4. Emulate Linux SIGPWR signal via FreeBSD SIGRTMIN signal which is outside of allowed on Linux signal numbers. PR: 197216 Changes: head/sys/amd64/linux/linux.h head/sys/amd64/linux/linux_machdep.c head/sys/amd64/linux/linux_sysvec.c head/sys/amd64/linux32/linux.h head/sys/amd64/linux32/linux32_machdep.c head/sys/amd64/linux32/linux32_sysvec.c head/sys/compat/linux/linux.c head/sys/compat/linux/linux.h head/sys/compat/linux/linux_fork.c head/sys/compat/linux/linux_misc.c head/sys/compat/linux/linux_signal.c head/sys/compat/linux/linux_signal.h head/sys/conf/files.amd64 head/sys/conf/files.i386 head/sys/i386/linux/linux.h head/sys/i386/linux/linux_machdep.c head/sys/i386/linux/linux_ptrace.c head/sys/i386/linux/linux_sysvec.c head/sys/modules/linux/Makefile head/sys/modules/linux_common/Makefile
A commit references this bug: Author: dchagin Date: Sat Jan 9 17:29:09 UTC 2016 New revision: 293575 URL: https://svnweb.freebsd.org/changeset/base/293575 Log: MFC r283474: Rework signal code to allow using it by other modules, like linprocfs: 1. Linux sigset always 64 bit on all platforms. In order to move Linux sigset code to the linux_common module define it as 64 bit int. Move Linux sigset manipulation routines to the MI path. 2. Move Linux signal number definitions to the MI path. In general, they are the same on all platforms except for a few signals. 3. Map Linux RT signals to the FreeBSD RT signals and hide signal conversion tables to avoid conversion errors. 4. Emulate Linux SIGPWR signal via FreeBSD SIGRTMIN signal which is outside of allowed on Linux signal numbers. PR: 197216 Changes: _U stable/10/ stable/10/sys/amd64/linux/linux.h stable/10/sys/amd64/linux/linux_machdep.c stable/10/sys/amd64/linux/linux_sysvec.c stable/10/sys/amd64/linux32/linux.h stable/10/sys/amd64/linux32/linux32_machdep.c stable/10/sys/amd64/linux32/linux32_sysvec.c stable/10/sys/compat/linux/linux.c stable/10/sys/compat/linux/linux.h stable/10/sys/compat/linux/linux_fork.c stable/10/sys/compat/linux/linux_misc.c stable/10/sys/compat/linux/linux_signal.c stable/10/sys/compat/linux/linux_signal.h stable/10/sys/conf/files.amd64 stable/10/sys/conf/files.i386 stable/10/sys/i386/linux/linux.h stable/10/sys/i386/linux/linux_machdep.c stable/10/sys/i386/linux/linux_ptrace.c stable/10/sys/i386/linux/linux_sysvec.c stable/10/sys/modules/linux/Makefile stable/10/sys/modules/linux_common/Makefile