Closed bilebucket closed 4 years ago
The problem is that window and rendering functions are required to be called from the main thread (sometimes it works if it is at least the same thread throughout the program execution). Since goroutines are not permanently tied to system threads by default, the foreign library calls may happen from any thread and even concurrently.
Someone needs to do the synchronization, making sure that at least all rendering and event processing functions (Set, Refresh, HasInput, Read, Peek, Delay) are called from the main thread. Ideally, all functions should be called from the same main thread because concurrent invocation of modification functions like Put or Print will mess with non-thread-safe internal state and crash the program.
It might be possible to isolate most of it in the library itself but 1) it has not been done in this version, and 2) it will introduce an overhead because the library will not know about the logical scope and will have to synchronize everything to the smallest bits.
It seems that in Go you need to use the LockOSThread function in the init function to bind the main goroutine to the main system thread and then run all the foreign library related code from that main goroutine.
The situation is not exactly unique to Go, and is usually solved either by running the whole program from the single thread (easiest but not quite Go way) or setting up a mechanism for executing pieces of code on a particular thread. In may be done by setting up a communication channel with the main thread and passing the library calls wrapped in lambdas/function objects to execute there in some loop on the main thread.
Indeed calling runtime.LockOS
seems to be the solution so I'm closing this issue for now. Thank you for the speedy and detailed response!
I've created a simple example utilizing the go bindings Gist.
Initially everything works as it should, but after some time (even without providing any keyboard input) the program hangs with
[fatal] 'refresh' was not called from the main thread
.Calling
blt.Delay
in main loop seems to make the hang less likely, but it still occurs after some time.I've yet to wrap my head around bealibterminals source to fully understand the reason for the hang but I've identified the line causing the hang.