From a88b6ee8db1928734a22a362554eab8f1e7550b8 Mon Sep 17 00:00:00 2001 From: David Crompton Date: Mon, 16 Jan 2023 14:13:08 +0100 Subject: [PATCH] showbase: Allow `destroy()` to be called from non-main thread Also adds an error message when `run()` is called from non-main thread Closes #1436 Fixes #1269 Co-authored-by: rdb --- direct/src/showbase/ShowBase.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index a65c2f173c..8c3555bf5f 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -583,7 +583,17 @@ class ShowBase(DirectObject.DirectObject): exitfunc and will be called at application exit time automatically. - This function is designed to be safe to call multiple times.""" + This function is designed to be safe to call multiple times. + + When called from a thread other than the main thread, this will create + a task to schedule the destroy on the main thread, and wait for this to + complete. + """ + + if Thread.getCurrentThread() != Thread.getMainThread(): + task = taskMgr.add(self.destroy, extraArgs=[]) + task.wait() + return for cb in self.finalExitCallbacks[:]: cb() @@ -3336,7 +3346,13 @@ class ShowBase(DirectObject.DirectObject): not running from within a p3d file. When we *are* within a p3d file, the Panda3D runtime has to be responsible for running the main loop, so we can't allow the application to do it. + + This method must be called from the main thread, otherwise an error is + thrown. """ + if Thread.getCurrentThread() != Thread.getMainThread(): + self.notify.error("run() must be called from the main thread.") + return if self.appRunner is None or self.appRunner.dummy or \ (self.appRunner.interactiveConsole and not self.appRunner.initialAppImport):