From 533bf953f987861bfacb3facb8403146a4c9fdcc Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 23 Apr 2020 21:08:55 +0200 Subject: [PATCH] app/internal/cocoainit: enable multithread support in Cocoa According to https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/20000738-125024 Cocoa is by default not multithread-safe for programs that use the posix api for creating threads: " For multithreaded applications, Cocoa frameworks use locks and other forms of internal synchronization to ensure they behave correctly. To prevent these locks from degrading performance in the single-threaded case, however, Cocoa does not create them until the application spawns its first new thread using the NSThread class. If you spawn threads using only POSIX thread routines, Cocoa does not receive the notifications it needs to know that your application is now multithreaded. When that happens, operations involving the Cocoa frameworks may destabilize or crash your application. " That includes Go programs. The fix, as discovered by Steeve Morin, is to create and launch an empty NSThread. Add a package that does that, and use it everywhere Cocoa is used. Sigh. Signed-off-by: Elias Naur --- app/headless/headless_darwin.go | 2 ++ app/internal/cocoainit/cocoa_darwin.go | 20 ++++++++++++++++++++ app/internal/log/log_ios.go | 2 ++ app/internal/window/os_macos.go | 2 ++ 4 files changed, 26 insertions(+) create mode 100644 app/internal/cocoainit/cocoa_darwin.go diff --git a/app/headless/headless_darwin.go b/app/headless/headless_darwin.go index 7282ae06..8b9b0e37 100644 --- a/app/headless/headless_darwin.go +++ b/app/headless/headless_darwin.go @@ -6,6 +6,8 @@ import ( "gioui.org/app/internal/glimpl" "gioui.org/gpu/backend" "gioui.org/gpu/gl" + + _ "gioui.org/app/internal/cocoainit" ) /* diff --git a/app/internal/cocoainit/cocoa_darwin.go b/app/internal/cocoainit/cocoa_darwin.go new file mode 100644 index 00000000..2a34e575 --- /dev/null +++ b/app/internal/cocoainit/cocoa_darwin.go @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +// Package cocoainit initializes support for multithreaded +// programs in Cocoa. +package cocoainit + +/* +#cgo CFLAGS: -xobjective-c -fmodules -fobjc-arc +#import + +static inline void activate_cocoa_multithreading() { + [[NSThread new] start]; +} +#pragma GCC visibility push(hidden) +*/ +import "C" + +func init() { + C.activate_cocoa_multithreading() +} diff --git a/app/internal/log/log_ios.go b/app/internal/log/log_ios.go index 11472e80..7de01076 100644 --- a/app/internal/log/log_ios.go +++ b/app/internal/log/log_ios.go @@ -16,6 +16,8 @@ import ( "io" "log" "unsafe" + + _ "gioui.org/app/internal/cocoainit" ) func init() { diff --git a/app/internal/window/os_macos.go b/app/internal/window/os_macos.go index 42c23fa8..9b4ee7d0 100644 --- a/app/internal/window/os_macos.go +++ b/app/internal/window/os_macos.go @@ -17,6 +17,8 @@ import ( "gioui.org/io/key" "gioui.org/io/pointer" "gioui.org/io/system" + + _ "gioui.org/app/internal/cocoainit" ) /*