unixint.d: unblock SIGSEGV before undoing wirte protection on envinronment
Doing it the other way around leads to race conditions, since an unlucky interrupt arriving just after the mprotect call (but before the the_env->disable_interrupts = 0 write) will write protect the environment again, leading to a segfault. This is no problem if SIGSEGV is unblocked (in which case we will just enter sigsegv_handler again and arrive at the same point). However if SIGSEGV is blocked (and another segfault arises) the whole process will die.
This commit is contained in:
parent
d8fbbb213e
commit
8d2b8d0ce1
1 changed files with 2 additions and 2 deletions
|
|
@ -789,17 +789,17 @@ handler_fn_prototype(sigsegv_handler, int sig, siginfo_t *info, void *aux)
|
|||
if (((char*)&the_env->disable_interrupts <= (char*)info->si_addr) &&
|
||||
((char*)info->si_addr < (char*)(&the_env->disable_interrupts+1)))
|
||||
{
|
||||
unblock_signal(the_env, sig);
|
||||
mprotect(the_env, sizeof(*the_env), PROT_READ | PROT_WRITE);
|
||||
the_env->disable_interrupts = 0;
|
||||
unblock_signal(the_env, sig);
|
||||
handle_all_queued_interrupt_safe(the_env);
|
||||
return;
|
||||
} else if (the_env->disable_interrupts &&
|
||||
((char*)(&the_env->disable_interrupts+1) <= (char*)info->si_addr) &&
|
||||
((char*)info->si_addr < (char*)(the_env+1))) {
|
||||
unblock_signal(the_env, sig);
|
||||
mprotect(the_env, sizeof(*the_env), PROT_READ | PROT_WRITE);
|
||||
the_env->disable_interrupts = 0;
|
||||
unblock_signal(the_env, sig);
|
||||
ecl_unrecoverable_error(the_env, interrupt_msg);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue