From ff64d87bb48a8bd7225984002032db90234b48ac Mon Sep 17 00:00:00 2001 From: der richter Date: Mon, 14 Oct 2024 21:47:37 +0200 Subject: [PATCH] mac/common: fix usage of vo struct after vo uninit race we keep track of the current vo struct to flag for events that are initiated async by various thread from different system notifications. the problem here is the usage of that vo struct after uninit. make accessing of that vo struct atomic and clear it on uninit, so it can't be used afterwards by concurrent threads from system notifications or events. Fixes #15088 --- video/out/cocoa_cb_common.swift | 5 +++-- video/out/mac/common.swift | 25 +++++++++++-------------- video/out/mac_common.swift | 4 ++-- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift index 6a3fcedada..70e9deb486 100644 --- a/video/out/cocoa_cb_common.swift +++ b/video/out/cocoa_cb_common.swift @@ -40,7 +40,7 @@ class CocoaCB: Common, EventSubscriber { } func preinit(_ vo: UnsafeMutablePointer) { - self.vo = vo + eventsLock.withLock { self.vo = vo } input = InputHelper(vo.pointee.input_ctx, option) if backendState == .uninitialized { @@ -57,12 +57,13 @@ class CocoaCB: Common, EventSubscriber { } func uninit() { + eventsLock.withLock { self.vo = nil } window?.orderOut(nil) window?.close() } func reconfig(_ vo: UnsafeMutablePointer) { - self.vo = vo + eventsLock.withLock { self.vo = vo } if backendState == .needsInit { DispatchQueue.main.sync { self.initBackend(vo) } } else if option.vo.auto_window_resize { diff --git a/video/out/mac/common.swift b/video/out/mac/common.swift index 7e3af8bd46..b4ef836501 100644 --- a/video/out/mac/common.swift +++ b/video/out/mac/common.swift @@ -22,7 +22,6 @@ class Common: NSObject { var option: OptionHelper var input: InputHelper? var log: LogHelper - var vo: UnsafeMutablePointer? let queue: DispatchQueue = DispatchQueue(label: "io.mpv.queue") @objc var window: Window? @@ -32,6 +31,7 @@ class Common: NSObject { var link: CVDisplayLink? let eventsLock = NSLock() + var vo: UnsafeMutablePointer? var events: Int = 0 var lightSensor: io_connect_t = 0 @@ -145,6 +145,7 @@ class Common: NSObject { } func uninitCommon() { + eventsLock.withLock { self.vo = nil } setCursorVisibility(true) stopDisplaylink() uninitLightSensor() @@ -455,23 +456,19 @@ class Common: NSObject { } func flagEvents(_ ev: Int) { - eventsLock.lock() - events |= ev - eventsLock.unlock() - - guard let vo = vo else { - log.warning("vo nil in flagEvents") - return + eventsLock.withLock { + events |= ev + guard let vo = vo else { return } + vo_wakeup(vo) } - vo_wakeup(vo) } func checkEvents() -> Int { - eventsLock.lock() - let ev = events - events = 0 - eventsLock.unlock() - return ev + eventsLock.withLock { + let ev = events + events = 0 + return ev + } } func windowDidEndAnimation() {} diff --git a/video/out/mac_common.swift b/video/out/mac_common.swift index d853c9c04a..8df82ce356 100644 --- a/video/out/mac_common.swift +++ b/video/out/mac_common.swift @@ -29,7 +29,7 @@ class MacCommon: Common { let log = LogHelper(mp_log_new(vo, vo.pointee.log, "mac")) let option = OptionHelper(vo, vo.pointee.global) super.init(option, log) - self.vo = vo + eventsLock.withLock { self.vo = vo } input = InputHelper(vo.pointee.input_ctx, option) presentation = Presentation(common: self) timer = PreciseTimer(common: self) @@ -41,7 +41,7 @@ class MacCommon: Common { } @objc func config(_ vo: UnsafeMutablePointer) -> Bool { - self.vo = vo + eventsLock.withLock { self.vo = vo } DispatchQueue.main.sync { let previousActiveApp = getActiveApp()