At Wed, 10 Jan 2018 11:17:14 -0800 (PST), Mark Wunsch wrote:
> The main question I have is: How does racket/gui set up and interact with
> the NSApplication's main thread?
> [...]
> My sense of this crash is that there's something inside the racket/gui
> internals [....]
> that works around a "typical" NSApplication start-up sequence that makes
> the osxvideosink code believe that it's running outside of the main NSApp
> thread. "Typical" is in quotes because I honestly have no idea what I'm
> talking about.
It's true that `racket/gui` avoids the usual run loop, so I expect that
"osxvideosink.m" will think that it needs its own. Specifically,
`[[NSRunLoop mainRunLoop] currentMode]` will return nil. And if
`gst_osx_videosink_check_main_run_loop` runs in the main OS thread via
a foreign call, then no events will be dispatched while it waits to
check in teh backup way, because the Racket-level thread that pulses
the main run loop will be blocked until the foreign call returns.
Finally, if "osxvideosink.m" sets up its own run loop and hacks
`isThread`, that would interact badly with `racket/gui` and could
explain the crash.
Does it help to wrap the `broadcast` call with
(call-atomically-in-run-loop
(lambda ()
....))
using the implementation of `call-atomically-in-run-loop` below?
----------------------------------------
#lang racket/base
(require racket/gui/base
ffi/unsafe
ffi/unsafe/objc
ffi/unsafe/nsalloc)
(provide call-atomically-in-run-loop)
(import-class NSObject NSArray NSRunLoop)
(define NSDefaultRunLoopMode (get-ffi-obj 'NSDefaultRunLoopMode #f _id))
(define-objc-class CallerContainer NSObject
[proc]
(-a _void (call) (proc)))
(define (call-atomically-in-run-loop proc)
(define result #f)
(define s (make-semaphore))
(call-with-autorelease
(lambda ()
(define obj (tell CallerContainer alloc))
(set-ivar! obj proc (lambda () (set! result (proc)) (semaphore-post s)))
(tellv (tell NSRunLoop mainRunLoop)
performSelector: #:type _SEL (selector call)
target: obj
argument: #f
order: #:type _uint 0
modes: (tell (tell NSArray alloc)
initWithObject: NSDefaultRunLoopMode))))
(yield s)
result)
;; Example, gets a non-#f result:
#;
(call-atomically-in-run-loop
(lambda ()
(tell (tell NSRunLoop mainRunLoop) currentMode)))