mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 03:29:43 -10:00
OSX/MACOS/COCOATOUCH: Normalise MRR safety in cocoa_gl_ctx.m
Audit of the OpenGL context driver turned up three latent MRR
leaks, all on the iOS/tvOS side where the code relies on ARC's
strong-store semantics for release-on-reassignment. Every
shipping iOS build currently enables ARC, so none of these leak
in practice today; making the paths MRR-safe as well brings the
driver in line with cocoa_common.m / ui_cocoa.m (which compile
under both ARC and MRR via the RARCH_*/RELEASE macro family) and
keeps the qb/make-style non-Xcode build viable for COCOATOUCH
targets.
All three fixes use the existing RELEASE macro from
cocoa_common.h, which under ARC expands to plain `x = nil` and
under MRR to `[x release]; x = nil` - so this is a no-op under
ARC and a strict correctness improvement under MRR.
- cocoa_gl_gfx_ctx_destroy: previously only the OSX branch called
RELEASE on g_ctx / g_hw_ctx; the iOS branch dropped the +1 from
[[EAGLContext alloc] initWithAPI:...] with a raw `g_ctx = nil`.
Move the RELEASE calls unconditional (post-#endif) and add
RELEASE(glk_view) under #if defined(HAVE_COCOATOUCH) so the
GLKView created in glkitview_init does not leak across
init/destroy cycles even on clean shutdown.
- cocoa_gl_gfx_ctx_set_video_mode (both branches): add defensive
RELEASE(g_ctx) / RELEASE(g_hw_ctx) before the
[[NSOpenGLContext alloc] ...] / [[EAGLContext alloc] ...]
overwrites. The normal reinit flow has -destroy running first
so both statics are already nil here, but guarding defensively
means a future re-init-without-destroy call site cannot leak
the previous +1.
- glkitview_init: release the previous glk_view before
overwriting with [GLKView new]. The existing
[glk_view deleteDrawable] handled the GL-side cleanup but left
the Obj-C retain dangling under MRR.
cocoa_vk_ctx.m has no static Obj-C pointers and needed no
changes. MoltenVK / vulkan_context_destroy own the Vulkan
surface / device lifetime, and all CocoaView accesses there are
brief unretained reads backed by cocoa_common.m's g_instance
strong reference (see 0062608).
This commit is contained in:
1 parent
0062608a13
commit
bd45086237
1 file changed
+34
-4
@@ -144,6 +144,11 @@ void *glkitview_init(void)
|
||||
* glPushGroupMarkerEXT with no current context and crashes. */
|
||||
if (glk_view)
|
||||
[glk_view deleteDrawable];
|
||||
/* RELEASE the old view (+1 from the previous [GLKView new]) before
|
||||
* overwriting the static. Under ARC the strong static would retain/
|
||||
* release on store, but under MRR the raw assignment below would drop
|
||||
* the +1 and leak one GLKView per re-init. */
|
||||
RELEASE(glk_view);
|
||||
|
||||
glk_view = [GLKView new];
|
||||
#if TARGET_OS_IOS
|
||||
@@ -172,10 +177,8 @@ static void cocoa_gl_gfx_ctx_destroy(void *data)
|
||||
#ifdef OSX
|
||||
[GLContextClass clearCurrentContext];
|
||||
[g_ctx clearDrawable];
|
||||
RELEASE(g_ctx);
|
||||
if (g_hw_ctx)
|
||||
[g_hw_ctx clearDrawable];
|
||||
RELEASE(g_hw_ctx);
|
||||
[GLContextClass clearCurrentContext];
|
||||
#else
|
||||
/* Clean up GLKView's framebuffer resources while context is still valid.
|
||||
@@ -185,8 +188,18 @@ static void cocoa_gl_gfx_ctx_destroy(void *data)
|
||||
[glk_view deleteDrawable];
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
#endif
|
||||
g_hw_ctx = nil;
|
||||
g_ctx = nil;
|
||||
/* RELEASE -releases + nils under MRR, just nils under ARC (see
|
||||
* cocoa_common.h). Doing this unconditionally matches the OSX
|
||||
* path's previous behaviour and fixes a latent iOS-MRR leak where
|
||||
* the +1 from [[EAGLContext alloc] initWithAPI:...] in set_video_mode
|
||||
* was dropped with a raw 'g_ctx = nil'. */
|
||||
RELEASE(g_ctx);
|
||||
RELEASE(g_hw_ctx);
|
||||
#if defined(HAVE_COCOATOUCH)
|
||||
/* glk_view was created with +new (+1) in glkitview_init. Release
|
||||
* it on destroy so it does not leak across init/destroy cycles. */
|
||||
RELEASE(glk_view);
|
||||
#endif
|
||||
|
||||
free(cocoa_ctx);
|
||||
}
|
||||
@@ -428,11 +441,21 @@ static bool cocoa_gl_gfx_ctx_set_video_mode(void *data,
|
||||
|
||||
if (cocoa_ctx->flags & COCOA_CTX_FLAG_USE_HW_CTX)
|
||||
{
|
||||
/* In the normal reinit flow -destroy runs before -set_video_mode
|
||||
* and both statics are already nil here; guard defensively so an
|
||||
* MRR build does not leak the previous +1 if that invariant ever
|
||||
* breaks (e.g. a future caller that re-inits without tearing
|
||||
* down first). Safe when already nil under both ARC and MRR. */
|
||||
RELEASE(g_ctx);
|
||||
RELEASE(g_hw_ctx);
|
||||
g_hw_ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
|
||||
g_ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:g_hw_ctx];
|
||||
}
|
||||
else
|
||||
{
|
||||
RELEASE(g_ctx);
|
||||
g_ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
|
||||
}
|
||||
|
||||
RELEASE(fmt);
|
||||
}
|
||||
@@ -611,6 +634,13 @@ static bool cocoa_gl_gfx_ctx_set_video_mode(void *data,
|
||||
{
|
||||
cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data;
|
||||
|
||||
/* In the normal reinit flow -destroy runs before -set_video_mode and
|
||||
* both statics are already nil here; guard defensively so an iOS-MRR
|
||||
* build does not leak the previous +1 if that invariant ever breaks
|
||||
* (e.g. a future caller that re-inits without tearing down first). */
|
||||
RELEASE(g_ctx);
|
||||
RELEASE(g_hw_ctx);
|
||||
|
||||
#if defined(HAVE_OPENGLES3)
|
||||
if (cocoa_ctx->flags & COCOA_CTX_FLAG_USE_HW_CTX)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user