While looking up the man pages for sigaction, I stumbled upon a confusing note in the Linux man pages:
On some architectures a union is involved: do not assign to both sa_handler and sa_sigaction(sigaction man page).
There are two possible ways to read it:
.sa_sigaction
and .sa_handler
in the same struct sigaction
..sa_sigaction
OR .sa_handler
in the whole project?struct sigaction sigactionArray[SIGNAL_SIGACTION_ARRAY_SIZE] = {
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_handler = SIG_IGN, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_IGN, .sa_flags = SA_NODEFER},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_handler = SIG_IGN, .sa_flags = SA_NODEFER},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_IGN, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_IGN, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_IGN, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_IGN, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_handler = SIG_DFL, .sa_flags = SA_NODEFER},
{.sa_sigaction = HandleBacktraceSignals, .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK}
};
According to interpretation 1. the above piece of code would be fine, but when definition 2. is right, it would be invalid since I mix.
Which one is true? Note: On my architecture, it is defined as a union
It's just talking about the same structure. It explains why: they might be part of a union
, so they use the same memory in the structure. E.g. it might actually be like:
struct sigaction {
union {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
},
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
Therefore, writing to one of them overwrites the other.