From 1d0fd9c40b3c822e7e24f878259c29e5e52a7885 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 8 Jan 2021 13:15:12 -0700 Subject: [PATCH] cs & thread: fix thread termination with pending timeout callback In other words, follow a note on line 77 of "atomic.rkt": ;; There's a small chance that `end-atomic-callback` ;; was set by the scheduler after the check and ;; before we exit atomic mode. Make sure that rare ;; possibility remains ok. That note was originally written in the context of changes for futures, but it also applies to plain old thread scheduling, where `engine-timeout` can be installed as a callback, but it's not allowed if an engine isn't running. --- racket/src/cs/schemified/thread.scm | 2 ++ racket/src/thread/atomic.rkt | 15 +++++++++++++-- racket/src/thread/schedule.rkt | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/racket/src/cs/schemified/thread.scm b/racket/src/cs/schemified/thread.scm index 02805a4cc7..85e2e35a5f 100644 --- a/racket/src/cs/schemified/thread.scm +++ b/racket/src/cs/schemified/thread.scm @@ -1938,6 +1938,7 @@ (loop_0 (cdr cbs_0))))))))) (loop_0 all-cbs_0)) (|#%app| host:enable-interrupts)))))) +(define flush-end-atomic-callbacks! (lambda () (end-atomic-callback 0))) (define future-block-for-atomic (lambda () (void))) (define set-future-block! (lambda (block_0) (set! future-block-for-atomic block_0))) @@ -12482,6 +12483,7 @@ (if (zero? (current-atomic)) (void) (internal-error "terminated in atomic mode!")) + (flush-end-atomic-callbacks!) (thread-dead! t_0) (if (eq? (unsafe-place-local-ref cell.1$1) t_0) (force-exit 0) diff --git a/racket/src/thread/atomic.rkt b/racket/src/thread/atomic.rkt index 313c33fdfa..4df745c7e7 100644 --- a/racket/src/thread/atomic.rkt +++ b/racket/src/thread/atomic.rkt @@ -22,11 +22,14 @@ future-barrier add-end-atomic-callback! + flush-end-atomic-callbacks! start-implicit-atomic-mode end-implicit-atomic-mode assert-atomic-mode + assert-no-end-atomic-callbacks + set-future-block!) ;; "atomically" is atomic within a place; when a future-running @@ -123,6 +126,9 @@ (loop (cdr cbs)))])) (host:enable-interrupts)) +(define (flush-end-atomic-callbacks!) + (end-atomic-callback 0)) + ;; ---------------------------------------- (define future-block-for-atomic (lambda () (void))) @@ -151,8 +157,13 @@ [(_) #`(unless (or (current-implicit-atomic) (positive? (current-atomic))) - (internal-error #,(format "should be in atomic mode: ~s" stx)))]))] + (internal-error #,(format "should be in atomic mode: ~s" stx)))])) + + (define (assert-no-end-atomic-callbacks) + (unless (eq? 0 (end-atomic-callback)) + (internal-error "non-empty end-atomic callbacks")))] #:off [(define-syntax-rule (start-implicit-atomic-mode) (begin)) (define-syntax-rule (end-implicit-atomic-mode) (begin)) - (define-syntax-rule (assert-atomic-mode) (begin))]) + (define-syntax-rule (assert-atomic-mode) (begin)) + (define-syntax-rule (assert-no-end-atomic-callbacks) (begin))]) diff --git a/racket/src/thread/schedule.rkt b/racket/src/thread/schedule.rkt index fcdc7a21cd..cbb5d34d47 100644 --- a/racket/src/thread/schedule.rkt +++ b/racket/src/thread/schedule.rkt @@ -132,6 +132,7 @@ (set-thread-engine! (current-thread/in-atomic) 'running)) (define (swap-in-engine e t leftover-ticks) + (assert-no-end-atomic-callbacks) (let loop ([e e] [prefix check-break-prefix]) (end-implicit-atomic-mode) (e @@ -149,6 +150,7 @@ (current-future #f) (unless (zero? (current-atomic)) (internal-error "terminated in atomic mode!")) + (flush-end-atomic-callbacks!) (thread-dead! t) (when (eq? root-thread t) (force-exit 0))