GNOME Bugzilla – Bug 686914
pygobject still requires GObject.threads_init()
Last modified: 2013-03-28 10:11:46 UTC
Created attachment 227328 [details] Test python program In C code g_threads_init() has recently been deprecated. But to use threads with python and pygobject, still requires a call to GObject.threads_init() or strange things happen. Is this solveable, or is GObject.threads_init() with us to stay? Will attach a test program. Uncomment the GObject.threads_init() line to make things work.
It is not documented, or at least it is not easily findable, that GObject.threads_init() should be called. While you must do it in pygtk, the reference for PyGObject is the standard gtk documentation which does not mention it.
Here a preliminary change to the wiki but this behavior should be documented somewhere in the python (c?) api. https://live.gnome.org/action/info/PyGObject/IntrospectionPorting?action=diff&rev2=23&rev1=22
pygobject itself hasn't called g_threads_init() for a long time, as it's deprecated and not necessary any more. pygobject's threads_init() is for Python thread handling (GIL), not for glib. I'd like to get rid of this as well, if someone has an idea how to elegantly call this automatically if threads are being used? Or would it hurt to just always call this, i. e. does it result in a measurable performance degradation?
While GObjects.threads_init() should be called before Gdk.init(), if the thread module is imported before a call to Gdk.init() or entering the main loop then most likely that function should be called. But this is not really a solution because lazy importing the thread module will break anyway.
It doesn't seem like any of the pyglib thread related functions are relevant any more. I replaced them with simple defines as follows in gi/_glib/pyglib.h: #define pyglib_threads_enabled() (TRUE) #define pyglib_gil_state_ensure PyGILState_Ensure #define pyglib_gil_state_release PyGILState_Release #define pyglib_begin_allow_threads Py_BEGIN_ALLOW_THREADS #define pyglib_end_allow_threads Py_END_ALLOW_THREADS With this, I verified the example script works fine without calling GObject.threads_init(). The reason this was needed is because pyglib_gil_state_ensure and like functions were no-ops based on an internal variable (pyglib_threads_enabled), this would cause problems because the GIL would not be managed in this case. Note Gdk.threads_init() is still needed if you want to call Gdk functions from a Python thread outside of the main thread. This is unrelated to GObject.threads_init. The only reason something like GObject.threads_init would ever be needed is if GLib.Thread was usable from python and had the ability to run Python code. In this case what is really needed is a call to PyEval_InitThreads AFAICT. But GLib.Thread does not work and I don't know if it ever will from within Python.
Created attachment 238275 [details] [review] Deprecate GLib and GObject threads_init Remove a handful of Python threading related helper functions from pyglib and pygobject. The binding internals required GLib.threads_init to be called for PyGObject to work with Python threads. This was removed as it should not be a requirement. Using the Python threading module already initializes threading for us (PyEval_InitThreads). Additional notes: * pyglib.h is not distributed so we don't need to worry about API breakage. * pygobject.h IS distributed so we need to keep set_thread_block_funcs around
Targeting 3.10 to avoid any potential disruption this late in the release cycle.
Comment on attachment 238275 [details] [review] Deprecate GLib and GObject threads_init Very nice, thanks Simon! This indeed helps to get rid of another weirdness.
Additional note: Make sure we don't regress bug 678046, ideally add a regression tests for that along with this patch.
Comment on attachment 238275 [details] [review] Deprecate GLib and GObject threads_init master has thawed, so please go ahead with this now. Thanks!
Attachment 238275 [details] pushed as 48e5221 - Deprecate GLib and GObject threads_init