What should I do if a new signal is received while processing the signal? Signal-related operation functions

If you don't know enough about the signal, you can check out this article: link

mask word related

Signal masks can be used to control which signals a process accepts when processing signals, so as to avoid receiving new signals when processing signals . The signal mask word is a bit vector, and each bit corresponds to a signal. If the bit is set to 1, it means that the signal is masked, that is, the process cannot accept the signal.

When a process handles a signal, the signal's signal mask word is set to mask the signal's bit, thus ensuring that the signal will not be sent to the process again while the signal handler is running. Before the signal handler returns, the process restores the signal mask to its original value, allowing additional signals to be received.

If the process needs to prevent receiving certain signals for a period of time, you can use the sigprocmask() function to modify the signal mask word. For example, certain signals can be blocked while a signal handler is running to ensure that no other signals are received while the current signal is being processed. Then when the signal handler returns, call the sigprocmask() function again to restore the original signal mask.
The process capture function sigaction can also achieve a similar effect

Implementation

The sigaction() function is a function for setting a signal handler. In Linux, it is one of the most commonly used functions for setting a signal handler. The following is the function prototype of the sigaction() function:

#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

The parameter signum indicates the signal number to be set,
the parameter act is a pointer to the struct sigaction structure, which is used to set a new signal handler, and the parameter oldact is a pointer to the struct sigaction structure, which is used to obtain the old signal handler.

The struct sigaction structure contains three members:

struct sigaction {
    
    
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
};

Among them, sa_handler and sa_sigaction are used to set the signal processing program,
sa_mask is used to set the signal mask word, which is only valid in the current capture function , in other words, only temporarily shield other signals in the capture function, so as to prevent interference by other signals
sa_flags is used to set the flag of the signal processing program. When it is set to 0, it means that this signal is shielded. In other words, when this signal is received again, it will be temporarily shielded and processed later. That is to say, it is not necessary to deliberately set sa_mask
sa_restorer for Save the original signal handler.

1.#include <stdio.h>  
2.#include <signal.h>  
3.#include <stdlib.h>  
4.#include <string.h>  
5.#include <unistd.h>  
6.#include <errno.h>  
7.#include <pthread.h>  
8.  
9.void sys_err(const char *str)  
10.{
    
      
11.    perror(str);  
12.    exit(1);  
13.}  
14.  
15.void sig_catch(int signo)                   // 回调函数  
16.{
    
      
17.    if (signo == SIGINT) {
    
      
18.        printf("catch you!! %d\n", signo);  
19.        sleep(10);  
20.    }  
21.      
22.    else if (signo == SIGQUIT)  
23.        printf("-----------catch you!! %d\n", signo);  
24.      
25.    return ;  
26.}  
27.  
28.int main(int argc, char *argv[])  
29.{
    
      
30.    struct sigaction act, oldact;  
31.  
32.    act.sa_handler = sig_catch;         // set callback function name       设置回调函数  
33.    sigemptyset(&(act.sa_mask));        // set mask when sig_catch working. 清空sa_mask屏蔽字, 只在sig_catch工作时有效  
34.    //sigaddset(&act.sa_mask, SIGQUIT);  
35.    act.sa_flags = 0;                   // usually use.                     默认值,b表示屏蔽本信号  
36.      
37.    int ret = sigaction(SIGINT, &act, &oldact);     //注册信号捕捉函数  
38.    if (ret == -1)  
39.        sys_err("sigaction error");  
40.    ret = sigaction(SIGQUIT, &act, &oldact);     //注册信号捕捉函数  
41.  
42.    while (1);  
43.  
44.    return 0;  
45.}  

What to do if a new signal is received while Linux is processing the signal

When Linux is processing a signal, if it receives a new signal of the same type (different types do not affect), because the signal processing priority is the highest,
it will decide how to handle this according to the type of signal and the setting of the signal handler of the process new signal.
Linux has two types of signals: reliable and unreliable. Reliable signals are queued for processing by a process, while unreliable signals may be lost.

in conclusion

For reliable signals , if Linux is processing a signal and receives a new signal of the same type, the new signal will be placed in the process's signal queue to be processed . If a process has an appropriate signal handler set, it handles each signal in queue order.

For unreliable signals , if Linux is processing a signal and a new signal of the same type is received, the new signal may be lost . This is because unreliable signals can be lost or overwritten by the kernel. If a process needs to handle unreliable signals, it should complete the current signal processing work as quickly as possible so that it can respond to new signals in a timely manner.
From the conclusion, during the execution of the capture function, the masked unreliable signal is sent multiple times, and it is only processed once after unmasking !
Signal Capture Features:

	1. 捕捉函数执行期间,信号屏蔽字 由 mask --> sa_mask , 捕捉函数执行结束。 恢复回mask

	2. 捕捉函数执行期间,本信号自动被屏蔽(sa_flgs = 0).

   3.捕捉函数执行期间,被屏蔽信号多次发送,解除屏蔽后只处理一次!

What are the unreliable signals and why are they lost?

In Linux, the last 32 signals are reliable, and the
common unreliable signals are as follows:
SIGALRM: timer signal, which will be triggered after a period of time, usually used for timeout detection and timers.
SIGIO: Asynchronous input and output signals for non-blocking IO operations.
SIGURG: Urgent data signal, used for TCP network data processing.
SIGPIPE: Pipe burst signal, used to detect whether the pipe is broken.
The reason non-reliable signals can be lost is that when the kernel sends a signal to a process, the signal is lost if it is overridden by a signal of the same type before being processed. This is because the kernel only keeps one pending signal per process, and if that signal is overridden, subsequent signals are ignored.

In addition, if the process performs a long-term operation while processing the signal, the process may not be able to process the subsequent signal in time, thus losing the signal. Therefore, when dealing with unreliable signals, it is necessary to pay attention to completing the current signal processing work as soon as possible, so as to be able to respond to subsequent signals in time.

Supplement: signal operation function

Signal set operation function:

sigset_t set;  自定义信号集。

sigemptyset(sigset_t *set);	清空信号集

sigfillset(sigset_t *set);	全部置1

sigaddset(sigset_t *set, int signum);	将一个信号添加到集合中

sigdelset(sigset_t *set, int signum);	将一个信号从集合中移除

sigismember(const sigset_t *set,int signum); 判断一个信号是否在集合中。 在--》1, 不在--》0

Set signal mask word and unmask:

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

	how:	SIG_BLOCK:	设置阻塞

		SIG_UNBLOCK:	取消阻塞

		SIG_SETMASK:	用自定义set替换mask。

	set:	自定义set

	oldset:旧有的 mask。

View pending signal sets:

int sigpending(sigset_t *set);

	set: 传出的 未决信号集。

Guess you like

Origin blog.csdn.net/qq_46017342/article/details/130027134