In a signal handler installed through void (*sa_sigaction)(int, siginfo_t *, void *);
, how can I tell whether a SIGILL originated from an illegal instruction or from some process having sent SIGILL? I looked at si_pid
of siginfo_t, but this seems to be uninitialized in case an illegal instruction was encountered, so that I can't base my decision on it. - Of course, I'm searching for a preferably simple and portable solution, rather than reading the instruction code at si_addr
and trying to determine if it is legal.
A bona fide SIGILL will have an si_code
of one of the ILL_ values (e.g., ILL_ILLADR). A user-requested SIGILL will have an si_code
of one of the SI_ values (often SI_USER).
The relevant POSIX values are:
[Kernel-generated]
ILL_ILLOPC Illegal opcode.
ILL_ILLOPN Illegal operand.
ILL_ILLADR Illegal addressing mode.
ILL_ILLTRP Illegal trap.
ILL_PRVOPC Privileged opcode.
ILL_PRVREG Privileged register.
ILL_COPROC Coprocessor error.
ILL_BADSTK Internal stack error.
[User-requested]
SI_USER Signal sent by kill().
SI_QUEUE Signal sent by the sigqueue().
SI_TIMER Signal generated by expiration of a timer set by timer_settime().
SI_ASYNCIO Signal generated by completion of an asynchronous I/O request.
SI_MESGQ Signal generated by arrival of a message on an empty message queue.
For example, the recipe in this question gives me ILL_ILLOPN, whereas kill(1)
and kill(2)
gives me zero (SI_USER).
Of course, your implementation might add values to the POSIX list. Historically, user- or process-generated si_code
values were <= 0, and this is still quite common. Your implementation might have a convenience macro to assist here, too. For example, Linux provides:
#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With