Is it possible to signal handler to survive after exec ?
No. From the man
pages:
execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded. The program invoked inherits the calling process's PID, and any open file descriptors that are not set to close on exec. Signals pending on the calling process are cleared. Any signals set to be caught by the calling process are reset to their default behaviour. The SIGCHLD signal (when set to SIG_IGN) may or may not be reset to SIG_DFL.
In fact, if the signal handler were still active after the code had been replaced with some very different code, you could expect all sorts of mayhem when the signal occurred. The signal handler is, after all, just an address to call when something happens (discounting SIG_IGN
and SIG_DFL
for now). Who knows what piece of code would be at that address when you replace the entire text segment?
Can't catch signals after exec
Signal masks are inherited across exec, and SIGINT is blocked during the invocation of your signal handler, which calls execve
. Thus your re-exec'd image is started with SIGINT blocked.
If you strace the process, you'll see that your signal
call becomes something like:
3143 rt_sigaction(SIGINT, {0xabcd, [INT], SA_RESTORER|SA_RESTART, 0xabcd}, {SIG_DFL, [], 0}, 8) = 0
^^^^^
|
+--- SIGINT is blocked during handler!
sigaction
will give you finer control over the signal handler, and is recommended over signal
.
What happens after the execution of a handler function on the SIGCHLD signal in C?
As @ChrisDodd said, the problem was that a system call (fgets), was interrupted by the death of the background process and caused undefined behaviour.
Therefore, I solved my problem by adding the following flag to my handler:
sa.sa_flags = SA_RESTART;
As the documentation says it will:
Provide behavior compatible with BSD signal semantics by making certain system calls restartable across signals.
Thus no more issue with fgets.
What happens when a signal is received while already in a signal handler?
In your concrete example (the same signal being received), the signal is delivered after the signal handler has finished (so bullet point #2 is correct). Note, however, that you may "lose" signals.
The reason for that is that while a signal is being inside its handler, it is blocked. Blocked signals are set to pending, but not queued. The term "pending" means that the operating system remembers that there is a signal waiting to be delivered at the next opportunity, and "not queued" means that it does this by setting a flag somewhere, but not by keeping an exact record of how many signals have arrived.
Thus, you may receive 2 or 3 (or 10) more SIGCHLD
while in your handler, but only see one (so in some cases, bullet point #1 can be correct, too).
Note that several flags that you can pass to sigaction
can affect the default behaviour, such as SA_NODEFER
(prevents blocking signal) and SA_NOCLDWAIT
(may not generate signal at all on some systems).
Now of course, if you receive a different type of signal, there's no guarantee that it won't interrupt your handler. For that reason, one preferrably doesn't use non signal safe functions.
different ways to ignore a signal?
if I want to ignore
SIGINT
signal, then I just need to simply code as:signal(SIGINT, SIG_IGN);
, is my understanding corrct?
Yes, but the docs for signal
recommend using sigaction
. signal
's semantics vary by system, while sigaction
's are more consistent.
does the compiler automacially inject this handler into the compiled code?
No. The compiler doesn't create an empty handler for SIG_IGN
. It literally tells the OS to ignore the signal for the process. It's not a function pointer but a value signal
treats specially.
since my own
sigint_handler
does nothing, it is pretty much like ignoring theSIGINT
, so can I say this approach is fundamentally the same assignal(SIGINT, SIG_IGN);
?
While both effectively ignore the signal, there are differences.
- When using a signal handler, a blocking syscall might return prematurely with error
EINTR
to allow the signal handler to run. This won't happen withSIG_IGN
. SIG_IGN
will surviveexec
, but a handler doesn't.- On some systems, the signals's disposition is reset to
SIG_DFL
when the signal handler is called, so your code would only ignore the first instance of the signal on such systems. - There are other differences, which may vary by platform.
Related Topics
Sftp on Linux Server Gives Error "Received Message Too Long"
Understanding Sendfile() and Splice()
Why Can't I Access Xampp's PHPmyadmin on Localhost? Access Is Forbidden
How to Write One Script That Runs in Bash/Shell and Powershell
Implementing Poll in a Linux Kernel Module
Problems Installing R on Linux Centos 6.2
Why Doesn't "History | Vim" Work
How to Load Jna Native Support Library Elasticsearch 6.X
Linux: Run Cron Job in Foreground
Can Gdb Change the Assembly Code of a Running Program
How to Create Tar for Files Older Than 7 Days Using Linux Shell Scripting
Gdb Can Not Open Shared Object File
How to Do Runtime Binding Based on CPU Capabilities on Linux
Pseudo-Random Stack Pointer Under Linux
How to Install R 3.1.2 on Linux Mint 17.1
How to Setup a Periodic Timer Callback in a Linux Kernel Module
How to Receive the Wrong Ethernet Frames and Disable the Crc/Fcs Calcul