| 1 | = Signal Support Revision = |
| 2 | |
| 3 | Haiku features basic support for POSIX signals, but that support is neither |
| 4 | complete nor fully compliant. To improve the situation several issues need |
| 5 | to be addressed. This document discusses the issues and proposes implementation |
| 6 | changes to address them. |
| 7 | |
| 8 | |
| 9 | == Issues with the Current Implementation == |
| 10 | |
| 11 | * (#5679) With the current implementation signals are only sent and delivered |
| 12 | to threads. A signal sent to a process is always delivered to its main |
| 13 | thread, which is incorrect. Instead the signal should be delivered to any |
| 14 | thread that doesn't block the signal. |
| 15 | * (#6704) There's no `SIGBUS` signal. The constant is defined to `SIGSEGV`. |
| 16 | POSIX requires both to be different. |
| 17 | * (#1935) Support for realtime signals is missing. This includes: |
| 18 | - The signal range SIGRTMIN through SIGRTMAX (minimum 8 signals). |
| 19 | - Signal queuing. |
| 20 | - The `sigaction()` `SA_SIGINFO` flag, i.e. `sigaction::sa_sigaction` style |
| 21 | signal handlers. |
| 22 | * `waitid()` is missing. It provides similar functionality as `waitpid()`, with |
| 23 | the addition of detailed signal information (a siginfo_t). |
| 24 | * `sigevent` support for timers and message queues: Since neither timers nor |
| 25 | message queues are implemented yet, this is merely something that needs to |
| 26 | be considered. |
| 27 | |
| 28 | There are several other, smaller details in which the current Haiku |
| 29 | implementation deviates from the standard. The implementation must be checked |
| 30 | carefully against the specification, particularly the |
| 31 | [http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04 conceptual overview]. |
| 32 | |
| 33 | |
| 34 | == Backwards Compatibility Considerations == |
| 35 | |
| 36 | Some of the required interface changes will cause backwards compatibility |
| 37 | issues: |
| 38 | * The addition of a separate `SIGBUS` might cause problems in programs that |
| 39 | expect it to be synomymous with `SIGSEGV`. Since neither can be ignored, it |
| 40 | will probably only affect the installation of handlers -- i.e. a `SIGBUS` |
| 41 | handler might not be installed although that would be desirable. Via symbol |
| 42 | versioning compatibility versions of `signal()` and `sigaction()` could |
| 43 | simply duplicate `SIGSEGV` calls for `SIGBUS`. A special flag would ask the |
| 44 | kernel to pass `SIGSEGV` instead of `SIGBUS` to the signal handler, when the |
| 45 | latter is delivered. |
| 46 | A source compatibility problem remains, when a program that hard-codes the |
| 47 | `SIGBUS == SIGSEGV` assumption (instead of using a preprocessor check) is |
| 48 | rebuilt. |
| 49 | * The addition of a separate `SIGBUS` constant and the new realtime signal |
| 50 | range will change NSIG and will also require a wider `sigset_t` type |
| 51 | (currently only 32 bit). Backwards binary compatibility can be achieved via |
| 52 | symbol versioning by providing compatibility versions of all affected |
| 53 | functions. |
| 54 | Source compatibility shouldn't be an issue for any program that uses the API |
| 55 | in a portable way (i.e. uses the type and functions provided for accessing |
| 56 | signal sets). |
| 57 | * The `sigaction()` `SA_SIGINFO`/`sigaction::sa_sigaction` support will not |
| 58 | affect binary or source compatibility. The `sa_sigaction` field will share |
| 59 | storage with `sa_handler`, so that the structure size remains unchanged |
| 60 | (save for the `sigset_t` size change that needs to be handled anyway). The |
| 61 | new feature is requested explicitly (via the `SA_SIGINFO` flag), so the old |
| 62 | BeOS specific signal handler extension can still be supported. |
| 63 | |
| 64 | |
| 65 | == Affected Components == |
| 66 | |
| 67 | * Signal functions: |
| 68 | - `kill()`, `killpg()`, `sigaltstack()`: Unaffected. |
| 69 | - `raise()`: Unaffected, but should be reimplemented to use `pthread_kill()` |
| 70 | as suggested by the standard. |
| 71 | - `pthread_kill()`: Unaffected, but must be moved to <signal.h>. |
| 72 | - `pthread_sigmask()`: |
| 73 | - Binary compatibility changes (sigset_t width). |
| 74 | - Must be moved to <signal.h>. |
| 75 | - `psiginfo()`, `psignal()`: Unimplemented. Print signal info to stderr. |
| 76 | - `sigaction()`: |
| 77 | - Binary compatibility changes (sigset_t width, `SIGBUS`). |
| 78 | - Support for `SA_SIGINFO`/`sigaction::sa_sigaction`. |
| 79 | - `sigaddset()`, `sigdelset()`, `sigemptyset()`, `sigfillset()`, |
| 80 | `sigismember()`: Binary compatibility changes (sigset_t width). |
| 81 | - `sighold()`, `sigignore()`, `sigpause()`, `sigrelse()`, `sigset()`, |
| 82 | `siginterrupt()`: Binary compatibility changes (`SIGBUS`). |
| 83 | - `signal()`: Binary compatibility changes (`SIGBUS`). |
| 84 | - `sigpending()`, `sigsuspend()`, `sigprocmask()`, `sigwait()`: |
| 85 | Binary compatibility changes (sigset_t width, `SIGBUS`). |
| 86 | - `sigtimedwait()`, `sigwaitinfo()`, `sigqueue()`: Unimplemented. |
| 87 | * wait[p]id() and the respective kernel implementation. |
| 88 | * Delivery of synchronous signals (SIGSEGV, SIGBUS, SIGFPE, etc.). |
| 89 | * Debugger interface: |
| 90 | - `B_DEBUG_MESSAGE_{S,G}ET_SIGNAL_MASKS`: Support signal masks for the team |
| 91 | and change the meaning of `debug_nub_{s,g}et_signal_masks::thread == -1` to |
| 92 | refer to those. |
| 93 | - `B_DEBUG_MESSAGE_{S,G}ET_SIGNAL_HANDLER`: Change the meaning of |
| 94 | `debug_nub_{s,g}et_signal_handler::thread == -1` to refer to the process. |
| 95 | - Binary compatibility does not need to be considered, since the debugger |
| 96 | interface is not BeOS compatible and is more or less experimental ATM. |
| 97 | |
| 98 | |
| 99 | == Implementation == |
| 100 | |
| 101 | * Change locking for process groups, teams, and threads. Currently there are |
| 102 | only two locks: The teams and the threads spinlock. Introduce per-process- |
| 103 | group, per-team, and per-thread mutexes protecting at least the child lists |
| 104 | and (for the team and thread) the signal structures. This will simplify the |
| 105 | signal handling code, as we don't have to disable interrupts (and hold |
| 106 | spinlocks) and will thus have more flexibility e.g. with respect to memory |
| 107 | allocations. |
| 108 | * Introduce per-team and per-thread signal queues. All signals -- with the |
| 109 | exception of `SIGKILL[THR]` (which need special handling) -- will be stored |
| 110 | in the queues as objects with all the required additional info (cf. |
| 111 | `siginfo_t`). Update kernel signal code respectively, including syscall |
| 112 | implementations and `handle_signal()`. |
| 113 | * Add a kernel-internal interface for delivering synchronous signals |
| 114 | (`SIGSEGV` etc.). |
| 115 | * Update the signal frame construction code to support `SA_SIGINFO` style |
| 116 | signal handlers. |
| 117 | * Add the missing signal functions (`sigqueue()` etc.). |
| 118 | * Update the userland signal functions and implement binary compatibility |
| 119 | wrappers. |
| 120 | * Update the job control/`wait_for_child()` code to support `waitid()` and |
| 121 | implement `waitid()`. |
| 122 | * Update the signal related part of the user debugger interface. |
| 123 | * Align the signals implementation with the POSIX "Signal Concepts" section. |