I'm learning about signals. I've created a simple code to handle a segmentation fault:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
volatile char *p = NULL;
void segv_handler(int signum) {
char text[100];
sprintf(text, "Segv handler! p: %p\n", p);
if (p == NULL)
p = malloc(sizeof p);
write(STDOUT_FILENO, text, strlen(text));
}
int main() {
signal(SIGSEGV, segv_handler);
*p = 1;
}
I imagined, that after unsuccessful dereference of the pointer p
my handler would allocate the memory for p
and reexecution of the *p = 1
would work properly. However, what's happening is that segfault happens indefinitely, even after allocating memory for p
.
I looked at the assembly generated by the compiler for the main function and it looks like this:
main:
.LFB7:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq segv_handler(%rip), %rax
movq %rax, %rsi
movl $11, %edi
call signal@PLT
movq p(%rip), %rax
movb $1, (%rax)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
As you can see, assembly instruction that causes the segfault is the movb $1, (%rax)
. Although allocating memory for p
worked as planned, the instruction does not use the new address of p
, so the segfault happens again.
This raises my question: can we somehow correct the code so it works as planned?