diff --git a/pkgs/racket-test-core/tests/racket/prompt.rktl b/pkgs/racket-test-core/tests/racket/prompt.rktl index 3a5e31de91..591cbcead3 100644 --- a/pkgs/racket-test-core/tests/racket/prompt.rktl +++ b/pkgs/racket-test-core/tests/racket/prompt.rktl @@ -464,6 +464,42 @@ ;; let's check that 3/4 were collected: (test #t < (hash-count ht) (* 1/4 (length l))))) +;;---------------------------------------- +;; Check that it works to apply a continuation that shares with +;; an enclosing continuation, where a runstack overflow happens +;; between the continuations + +(let () + (define N 100) + (define N2 10) + (define M 10) + + (define p (make-continuation-prompt-tag)) + + (define (grab n m k-prev q) + (cond + [(positive? n) + (let ([x (grab (sub1 n) m k-prev q)]) + (lambda () x))] + [(positive? m) + ((call/cc + (lambda (k) + (grab N2 (sub1 m) k q)) + p))] + [(positive? q) + (call-with-continuation-prompt + (lambda () + (k-prev + (lambda () + (grab N M void (sub1 q))))) + p)] + [else void])) + + (call-with-continuation-prompt + (lambda () + (grab N M void 10)) + p)) + ;;---------------------------------------- (report-errs) diff --git a/racket/src/racket/src/fun.c b/racket/src/racket/src/fun.c index 5ef923b721..32c8416e96 100644 --- a/racket/src/racket/src/fun.c +++ b/racket/src/racket/src/fun.c @@ -4793,6 +4793,8 @@ static Scheme_Saved_Stack *copy_out_runstack(Scheme_Thread *p, size = p->runstack_size - (runstack XFORM_OK_MINUS runstack_start); } + MZ_ASSERT(size <= p->runstack_size); + saved->runstack_size = size; start = MALLOC_N(Scheme_Object*, size); saved->runstack_start = start; @@ -5934,11 +5936,12 @@ static void restore_continuation(Scheme_Cont *cont, Scheme_Thread *p, int for_pr Scheme_Cont *rs_cont = cont; Scheme_Saved_Stack *saved, *actual; int delta = 0; - while (rs_cont->buf_ptr->buf.cont) { + while (rs_cont->buf_ptr->buf.cont + && (rs_cont->buf_ptr->buf.cont->runstack_start == cont->runstack_start)) { delta += rs_cont->runstack_copied->runstack_size; rs_cont = rs_cont->buf_ptr->buf.cont; - if (rs_cont->runstack_copied->runstack_size) { - delta -= 1; /* overlap for not-saved call/cc argument */ + if (rs_cont->runstack_copied->runstack_size > MAX_CALL_CC_ARG_COUNT) { + delta -= MAX_CALL_CC_ARG_COUNT; /* overlap for not-saved call/cc argument */ } } actual = NULL; @@ -5954,6 +5957,7 @@ static void restore_continuation(Scheme_Cont *cont, Scheme_Thread *p, int for_pr } else { meta_prompt->runstack_boundary_start = MZ_RUNSTACK_START; meta_prompt->runstack_boundary_offset = (MZ_RUNSTACK - MZ_RUNSTACK_START) + saved->runstack_size + delta; + MZ_ASSERT(meta_prompt->runstack_boundary_offset <= scheme_current_thread->runstack_size); } }