thread_pthread.c: allocate sigaltstack before pthread_create

A new (not-initialized-yet) pthread attempts to allocate sigaltstack by
using xmalloc.  It may cause GC, but because the thread is not
initialized yet, ruby_native_thread_p() returns false, which leads to
"[FATAL] failed to allocate memory" and exit.

In fact, we can observe the error message in the log of OpenBSD CI:
20200306T083005Z.log.html.gz

This changeset allocates sigaltstack before pthread is created.
This commit is contained in:
Yusuke Endoh 2020-03-06 21:32:42 +09:00
parent baaf681570
commit 0256e4f0f5
3 changed files with 27 additions and 8 deletions

View file

@ -547,14 +547,25 @@ rb_sigaltstack_size(void)
return size;
}
static int rb_sigaltstack_size_value = 0;
void *
rb_allocate_sigaltstack(void)
{
if (!rb_sigaltstack_size_value) {
rb_sigaltstack_size_value = rb_sigaltstack_size();
}
return xmalloc(rb_sigaltstack_size_value);
}
/* alternate stack for SIGSEGV */
void *
rb_register_sigaltstack(void)
rb_register_sigaltstack(void *altstack)
{
stack_t newSS, oldSS;
newSS.ss_size = rb_sigaltstack_size();
newSS.ss_sp = xmalloc(newSS.ss_size);
newSS.ss_size = rb_sigaltstack_size_value;
newSS.ss_sp = altstack;
newSS.ss_flags = 0;
sigaltstack(&newSS, &oldSS); /* ignore error. */
@ -1561,7 +1572,7 @@ Init_signal(void)
force_install_sighandler(SIGILL, (sighandler_t)sigill, &default_sigill_handler);
#endif
#ifdef SIGSEGV
RB_ALTSTACK_INIT(GET_VM()->main_altstack);
RB_ALTSTACK_INIT(GET_VM()->main_altstack, rb_allocate_sigaltstack());
force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler);
#endif
}