Friday Dec 08, 2006
Friday Dec 08, 2006
Having asked a number of colleagues I failed to find a consistent answer to the question of the differences between SIGBUS and SIGSEGV. According to the Solaris signal(3head) man page we have:
Name Value Default Event
...
SIGBUS 10 Core Bus Error
SIGSEGV 11 Core Segmentation Fault
So I dug a bit further and found that siginfo_t can tell you more about the origins of the signal, in particular we have, from the siginfo.h(3head) man page:
Signal Code Reason
_________________________________________________________________________
...
_________________________________________________________________________
SIGSEGV SEGV_MAPERR address not mapped to object
SEGV_ACCERR invalid permissions for mapped object
_________________________________________________________________________
SIGBUS BUS_ADRALN invalid address alignment
BUS_ADRERR non-existent physical address
BUS_OBJERR object specific hardware error
_________________________________________________________________________
Obviously this may be open to interpretation but that clarifies a few things for me.
For the techie take a look at the OpenSolaris source code for the trap() function. Here we see the handling for various types of trap including page faults. For example, there's a section where a decision is made as to return SIGBUS or SIGSEGV:
case T_WIN_OVERFLOW + T_USER: /* window overflow in ??? */
case T_WIN_UNDERFLOW + T_USER: /* window underflow in ??? */
case T_SYS_RTT_PAGE + T_USER: /* window underflow in user_rtt */
case T_INSTR_MMU_MISS + T_USER: /* user instruction mmu miss */
case T_DATA_MMU_MISS + T_USER: /* user data mmu miss */
case T_DATA_PROT + T_USER: /* user data protection fault */
switch (type) {
...
/*
* In the case where both pagefault and grow fail,
* set the code to the value provided by pagefault.
*/
(void) instr_size(rp, &addr, rw);
bzero(&siginfo, sizeof (siginfo));
siginfo.si_addr = addr;
if (FC_CODE(res) == FC_OBJERR) {
siginfo.si_errno = FC_ERRNO(res);
if (siginfo.si_errno != EINTR) {
siginfo.si_signo = SIGBUS;
siginfo.si_code = BUS_OBJERR;
fault = FLTACCESS;
}
} else { /* FC_NOMAP || FC_PROT */
siginfo.si_signo = SIGSEGV;
siginfo.si_code = (res == FC_NOMAP) ?
SEGV_MAPERR : SEGV_ACCERR;
fault = FLTBOUNDS;
}
I was digging around this following a discussion regarding bug 6466257 (mmap file writing fails on nfs3 client with EMC nas device) and the signals delivered by mmap(2). The man page suggests that either SIGBUS or SIGSEGV can be returned for a number of error conditions but doesn't seem sure which. The answer is, "it depends".
So my conclusion is sadly another question - can an application developer infer anything from a SIGBUS versus a SIGSEGV? The answer, I believe, is yes - but quite often the result is the same which is to fix the code