avoid stack-overflow in scheduler-triggered foreign calls

While a foreigh call is normally guarded by a check on the amount
of available stack space, a callbacks triggered by the
scheduler will first put Racket in no-stack-overflow mode, and
then it's too late to check stack space before making further
foreign calls. With Cocoa, there's some chance that the process
will run out of space. Avoid the mismatch by checking the stack
availability at the start of a scheduler iteration.
This commit is contained in:
Matthew Flatt 2014-09-17 15:53:03 +02:00
parent bb116e476a
commit 43d6684ab9

View File

@ -4882,6 +4882,17 @@ static void find_next_thread(Scheme_Thread **return_arg) {
next = NULL;
}
static Scheme_Object *do_thread_block()
{
Scheme_Thread *p = scheme_current_thread;
float sleep_time = p->sleep_end;
p->sleep_end = 0.0;
scheme_thread_block(sleep_time);
return scheme_false;
}
void scheme_thread_block(float sleep_time)
/* If we're blocked, `sleep_time' is a max sleep time,
not a min sleep time. Otherwise, it's a min & max sleep time.
@ -4922,6 +4933,17 @@ void scheme_thread_block(float sleep_time)
shrink_cust_box_array();
/* Scheduling queries might involve callbacks through the FFI that put
the runtime system into `scheme_no_stack_overflow` mode. Immitate
the foriegn-call entry point with an extra check that we have enough
stack to survive in foreign functions. */
if (!scheme_no_stack_overflow && scheme_is_stack_too_shallow()) {
p->sleep_end = sleep_time; /* an abuse of the `sleep_end` field to
pass `sleep_end` along */
(void)scheme_handle_stack_overflow(do_thread_block);
return;
}
if (scheme_active_but_sleeping)
scheme_wake_up();