= Signal Support Revision = Haiku features basic support for POSIX signals, but that support is neither complete nor fully compliant. To improve the situation several issues need to be addressed. This document discusses the issues and proposes implementation changes to address them. == Issues with the Current Implementation == * (#5679) With the current implementation signals are only sent and delivered to threads. A signal sent to a process is always delivered to its main thread, which is incorrect. Instead the signal should be delivered to any thread that doesn't block the signal. * (#6704) There's no `SIGBUS` signal. The constant is defined to `SIGSEGV`. POSIX requires both to be different. * (#1935) Support for realtime signals is missing. This includes: - The signal range SIGRTMIN through SIGRTMAX (minimum 8 signals). - Signal queuing. - The `sigaction()` `SA_SIGINFO` flag, i.e. `sigaction::sa_sigaction` style signal handlers. * `waitid()` is missing. It provides similar functionality as `waitpid()`, with the addition of detailed signal information (a siginfo_t). * `sigevent` support for timers and message queues: Since neither timers nor message queues are implemented yet, this is merely something that needs to be considered. There are several other, smaller details in which the current Haiku implementation deviates from the standard. The implementation must be checked carefully against the specification, particularly the [http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04 conceptual overview]. == Backwards Compatibility Considerations == Some of the required interface changes will cause backwards compatibility issues: * The addition of a separate `SIGBUS` might cause problems in programs that expect it to be synomymous with `SIGSEGV`. Since neither can be ignored, it will probably only affect the installation of handlers -- i.e. a `SIGBUS` handler might not be installed although that would be desirable. Via symbol versioning compatibility versions of `signal()` and `sigaction()` could simply duplicate `SIGSEGV` calls for `SIGBUS`. A special flag would ask the kernel to pass `SIGSEGV` instead of `SIGBUS` to the signal handler, when the latter is delivered. A source compatibility problem remains, when a program that hard-codes the `SIGBUS == SIGSEGV` assumption (instead of using a preprocessor check) is rebuilt. * The addition of a separate `SIGBUS` constant and the new realtime signal range will change NSIG and will also require a wider `sigset_t` type (currently only 32 bit). Backwards binary compatibility can be achieved via symbol versioning by providing compatibility versions of all affected functions. Source compatibility shouldn't be an issue for any program that uses the API in a portable way (i.e. uses the type and functions provided for accessing signal sets). * The `sigaction()` `SA_SIGINFO`/`sigaction::sa_sigaction` support will not affect binary or source compatibility. The `sa_sigaction` field will share storage with `sa_handler`, so that the structure size remains unchanged (save for the `sigset_t` size change that needs to be handled anyway). The new feature is requested explicitly (via the `SA_SIGINFO` flag), so the old BeOS specific signal handler extension can still be supported. == Affected Components == * Signal functions: - `kill()`, `killpg()`, `sigaltstack()`: Unaffected. - `raise()`: Unaffected, but should be reimplemented to use `pthread_kill()` as suggested by the standard. - `pthread_kill()`: Unaffected, but must be moved to . - `pthread_sigmask()`: - Binary compatibility changes (sigset_t width). - Must be moved to . - `psiginfo()`, `psignal()`: Unimplemented. Print signal info to stderr. - `sigaction()`: - Binary compatibility changes (sigset_t width, `SIGBUS`). - Move signal handler from thread to team. - Support for `SA_SIGINFO`/`sigaction::sa_sigaction`. - `sigaddset()`, `sigdelset()`, `sigemptyset()`, `sigfillset()`, `sigismember()`: Binary compatibility changes (sigset_t width). - `sighold()`, `sigignore()`, `sigpause()`, `sigrelse()`, `sigset()`, `siginterrupt()`: Binary compatibility changes (`SIGBUS`). - `signal()`: Binary compatibility changes (`SIGBUS`). - `sigpending()`, `sigsuspend()`, `sigprocmask()`, `sigwait()`: Binary compatibility changes (sigset_t width, `SIGBUS`). - `sigtimedwait()`, `sigwaitinfo()`, `sigqueue()`: Unimplemented. * wait[p]id() and the respective kernel implementation. * Delivery of synchronous signals (SIGSEGV, SIGBUS, SIGFPE, etc.). * Debugger interface: - `B_DEBUG_MESSAGE_{S,G}ET_SIGNAL_MASKS`: Support signal masks for the team and change the meaning of `debug_nub_{s,g}et_signal_masks::thread == -1` to refer to those. - `B_DEBUG_MESSAGE_{S,G}ET_SIGNAL_HANDLER`: Remove `debug_nub_{s,g}et_signal_handler::thread` as only the whole process has a signal handlers, not individual threads. - Binary compatibility does not need to be considered, since the debugger interface is not BeOS compatible and is more or less experimental ATM. == Implementation == * Change locking for process groups, teams, and threads. Currently there are only two locks: The teams and the threads spinlock. Introduce per-process- group, per-team, and per-thread mutexes protecting at least the child lists and (for the team and thread) the signal structures. This will simplify the signal handling code, as we don't have to disable interrupts (and hold spinlocks) and will thus have more flexibility e.g. with respect to memory allocations. * Introduce per-team and per-thread signal queues. All signals -- with the exception of `SIGKILL[THR]` (which need special handling) -- will be stored in the queues as objects with all the required additional info (cf. `siginfo_t`). Update kernel signal code respectively, including syscall implementations and `handle_signal()`. * Add a kernel-internal interface for delivering synchronous signals (`SIGSEGV` etc.). * Update the signal frame construction code to support `SA_SIGINFO` style signal handlers. * Add the missing signal functions (`sigqueue()` etc.). * Update the userland signal functions and implement binary compatibility wrappers. * Update the job control/`wait_for_child()` code to support `waitid()` and implement `waitid()`. * Update the signal related part of the user debugger interface. * Align the signals implementation with the POSIX "Signal Concepts" section. == Progress == * Implemented team/thread locking changes (up to r41498).