racket / racket

The Racket repository
https://racket-lang.org/
Other
4.82k stars 661 forks source link

internal error calling os-async-channel-put from finalizer #3842

Closed rmculpepper closed 3 years ago

rmculpepper commented 3 years ago

The following program causes Racket to go into an error-reporting loop:

#lang racket/base
(require ffi/unsafe
         ffi/unsafe/os-async-channel)

(let ()  ;; if `begin`, no problem
  (define c (make-os-async-channel))
  (register-finalizer (list c)
                      (lambda (cs)
                        (os-async-channel-put (car cs) #f))))

(for ([i 100])
  (sleep 0.01)
  (collect-garbage))

When the program is run, Racket prints the following in a loop:

internal error: attempt to deschedule the current thread in atomic mode
exception raised by exception handler: abort-current-continuation: contract violation
  expected: continuation-prompt-tag?
  given: [?error-value->string-handler not ready?]; original exception raised: internal error: attempt to deschedule the current thread in atomic mode
  context...: [omitted]

If the let is replaced with begin (so the definition keeps the os-async-channel reachable), the error disappears.

I ran into this issue while trying to minimize another bug. I don't think I actually depend on being able to write to an unreachable os-async-channel.

mflatt commented 3 years ago

The initial error is "mutex-acquire: mutex is defunct". It looks like the solution is probably to change Chez Scheme's guardian for mutexes and condition variables to be an ordered guardian, and I'm testing that repair.