Reputation: 94830
I was just wondering how segmentation faults might get reported.
Which one of these reports the segmentation faults (just an example), and how?
Upvotes: 4
Views: 162
Reputation: 112366
okay, to start with, a segmentation fault happens when the CPU attempts to access an address to which the process doesn't have access. At the lowest level, the implementation of memory mapping has to detect that, which in general produces an interrupt. The kernel receives that interrupt, and has a table of addresses of other segments of code, each of which is intended to handle that interrupt.
When the kernel receives that interrupt, it translates it into a specific value (I'm being vague because the exact details vary both with hardware architecture and kernel implementation). SIGSEGV
is usually defined to have the value 11, but the exact value isn't important; it's defined in signal.h
.
At that point, the signal value is passed to another table inside the kernel, which contains the addresses of "signal handlers". One of those handlers is at the offset represented by SIGSEGV
. Unless you have done something to change it, that address is usually of a routine that causes a core dump, assuming the appropriate limits permit, but you can replace that with the address of your own routine, which can do anything you like.
Upvotes: 1
Reputation: 46043
You can have some code like this which will call the GDB command to dump the call trace:
void BacktraceOnSegv() {
struct sigaction action = {};
action.sa_handler = DumpBacktrace;
if (sigaction(SIGSEGV, &action, NULL) < 0) {
perror("sigaction(SEGV)");
}
}
void DumpBacktrace(int) {
pid_t dying_pid = getpid();
pid_t child_pid = fork();
if (child_pid < 0) {
perror("fork() while collecting backtrace:");
} else if (child_pid == 0) {
char buf[1024];
sprintf(buf, "gdb -p %d -batch -ex bt 2>/dev/null | "
"sed '0,/<signal handler/d'", dying_pid);
const char* argv[] = {"sh", "-c", buf, NULL};
execve("/bin/sh", (char**)argv, NULL);
_exit(1);
} else {
waitpid(child_pid, NULL, 0);
}
_exit(1);
}
Here is an implementation that support more platforms.
Upvotes: 2
Reputation: 753695
If you take a look at the functions wait()
or waitpid()
, you will find that one of the bits in the exit status indicates a core dump. The POSIX specification mentions WIFSIGNALED
[sic] and WTERMSIG
to get the signal that terminated the process. The POSIX specification doesn't mention it, but on Mac OS X (10.7.4) for example, there's a WCOREDUMP()
macro to test whether a core file was created.
Upvotes: 2
Reputation: 798626
The process will just die, so obviously it cannot report it.
This is actually false. It is possible to install a SIGSEGV
handler to replace the default one, which simply dumps core and dies. A preload library can do so to catch a segmentation violation and use the limited facilities available to notify another process running on the system of what has happened before exiting.
Upvotes: 3