From event notification to action
Linux signals can arise from kernel events or sending interfaces and can target a process or a thread. A disposition selects the default action, ignoring or a handler; default actions include termination, stopping and continuing.
Dispositions are process-wide, whereas each thread has its own signal mask. A process-directed signal can be delivered to one eligible unblocked thread, not necessarily handled once by every thread.
References: [1]
Blocking differs from ignoring
Blocking generally defers delivery and leaves a signal pending, unlike choosing to ignore it. SIGKILL and SIGSTOP cannot be caught, blocked or ignored, so no application handler can intercept every signal.
Repeated instances of one standard signal do not accumulate while it is pending; later unblocking can yield one delivery. Real-time signals support queued instances and ordering rules, within resource limits, rather than a guaranteed hard-real-time response deadline.
References: [1]
Handlers interrupt existing user-space execution
Delivery can temporarily transfer a thread to its user-space handler and then restore its interrupted state. It does not automatically create another thread, and can interrupt library code while internal data is partly updated.
Async-signal-safety limits callable functions. Buffered stdio such as printf illustrates why reentering partially updated shared state is unsafe. More complex work can instead use designs such as synchronous signal acceptance rather than arbitrary calls from an asynchronous handler.