Signals are not returned properly through execv ()

I am writing a system-critical program for a Linux distribution that I am developing. He must restart himself when receiving certain signals in order to avoid failures. The problem is that after restarting, I cannot re-enable this signal. That is, the signal cannot be received twice. After execv () is run, when the new process calls signal () to configure the signal, SIG_DFL is returned. Everytime. Even if I call him twice in a row, it means that he was never installed in the first place. Is some weird flag wrapped from the original process?

+3
source share
2 answers

You are falling because you are trying to recursively process the signal.

When using signal()a signal handler for registration, this signal number is blocked until the signal handler returns - in fact, the / libc kernel blocks this signal number when the signal handler is called and unlocks it after the signal handler returns, since you never return from the signal handler (instead, you are a execlnew binary), SIGUSR1remains blocked and therefore does not fall a second time.

This can be seen by examining /proc/</pid>/statusbefore and after sending the first SIGUSR1.

Before:

$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000000
SigCgt: 0000000000000200

After:

$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000200
SigCgt: 0000000000000200

, SigCgt , 10 ( - , 10 , SIGUSR1, . man signal(7) ). SigBlk SIGUSR , SIGUSR1.

:

). SIGUSR execl sighandler:

sigset_t sigs;
sigprocmask(0, 0, &sigs);
sigdelset(&sigs, SIGUSR1);
sigprocmask(SIG_SETMASK, &sigs);

). sigaction SA_NODEFER signal . SIGUSR1 :

struct sigaction act;
act.sa_handler = signalhandler;
act.sa_mask = 0;
act.sa_flags = SA_NODEFER;
sigaction(SIGUSR1, &act, 0);
+8

exec, exec , , reset, . , reset, , , SIG_IGN, pre exec.

+1

Source: https://habr.com/ru/post/1710946/


All Articles