wiki:Obsolete/Proposals/SignalSupportRevision

Version 6 (modified by bonefish, 8 years ago) (diff)

--

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 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 <signal.h>.
    • pthread_sigmask():
      • Binary compatibility changes (sigset_t width).
      • Must be moved to <signal.h>.
    • psiginfo(), psignal(): Unimplemented. Print signal info to stderr.
    • sigaction():
      • Binary compatibility changes (sigset_t width, SIGBUS).
      • Move signal handlers 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 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 hrev41498).
  • Moved signal actions from thread to team (in hrev41522).
  • Added support for sending signals to teams (in hrev41560).