I’m trying to run the logic of my app in a separate thread. I followed the instructions from Threads & Concurrency - PyGObject by using GLib.idle_add where needed. However, my app freezes upon closing the window. The only thing I do from the thread is to connect to the “close-request” signal. The callback is executed and the thread terminates cleanly, so I don’t understand what is blocking afterward.
The problem is that in using connect as an idle handler, you’re returning the signal handler ID, a value equivalent to True (aka GLib.SOURCE_CONTINUE) and so you’re calling that function continuously. Just use a new function that returns GLib.SOURCE_REMOVE (technically it’ll also work if you let it return None).
I don’t see any obvious problems with your example. You’ve got the basic idea correct: by connecting to the signal in an idle callback that runs on the main thread, you avoid threadsafety problems. Not doing that is the common threading mistake. And then you cancel the python event on the main thread, which should end the wait on the secondary thread. It looks good to me. I’m not sure why it doesn’t work. We must be missing something.
Too bad Discourse didn’t show me your post before I responded, considering you posted a full 11 minutes before I did. Oh well.
Good point. You just have to be certain the object is still valid at the time you connect to its signal. As long as you’re certain it’s still alive, then it’s OK to connect from whatever thread you want. The thread you connect from has no impact on which thread the signal will be emitted from. In this case, app is a global object and you know it’s guaranteed to be valid for the lifetime of your thread, so you don’t need to use the idle callback after all. However, if you were doing anything more complex than just connecting a signal handler, you would still need it.