mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 15:45:38 +00:00
533bf953f9
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 <mail@eliasnaur.com>
50 lines
902 B
Go
50 lines
902 B
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
// +build darwin,ios
|
|
|
|
package log
|
|
|
|
/*
|
|
#cgo CFLAGS: -Werror -fmodules -fobjc-arc -x objective-c
|
|
|
|
#include "log_ios.h"
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"log"
|
|
"unsafe"
|
|
|
|
_ "gioui.org/app/internal/cocoainit"
|
|
)
|
|
|
|
func init() {
|
|
// macOS Console already includes timstamps.
|
|
log.SetFlags(log.Flags() &^ log.LstdFlags)
|
|
log.SetOutput(newNSLogWriter())
|
|
}
|
|
|
|
func newNSLogWriter() io.Writer {
|
|
r, w := io.Pipe()
|
|
go func() {
|
|
// 1024 is an arbitrary truncation limit, taken from Android's
|
|
// log buffer size.
|
|
lineBuf := bufio.NewReaderSize(r, 1024)
|
|
// The buffer to pass to C, including the terminating '\0'.
|
|
buf := make([]byte, lineBuf.Size()+1)
|
|
cbuf := (*C.char)(unsafe.Pointer(&buf[0]))
|
|
for {
|
|
line, _, err := lineBuf.ReadLine()
|
|
if err != nil {
|
|
break
|
|
}
|
|
copy(buf, line)
|
|
buf[len(line)] = 0
|
|
C.nslog(cbuf)
|
|
}
|
|
}()
|
|
return w
|
|
}
|