After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 556250 - non-async functions don't release python locks before calling blocking C functions
non-async functions don't release python locks before calling blocking C func...
Status: RESOLVED FIXED
Product: pygobject
Classification: Bindings
Component: gio
unspecified
Other Linux
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
: 569772 (view as bug list)
Depends on:
Blocks: 569774
 
 
Reported: 2008-10-14 11:16 UTC by Tim-Philipp Müller
Modified: 2009-02-20 22:30 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
patch adding threads unblock (7.00 KB, patch)
2009-02-14 22:43 UTC, Gian Mario Tagliaretti
committed Details | Review
Test if main loop is blocked (1.38 KB, text/x-python)
2009-02-15 23:08 UTC, John Stowers
  Details
Test if mainloop is blocked (1.30 KB, text/x-python)
2009-02-16 23:12 UTC, John Stowers
  Details

Description Tim-Philipp Müller 2008-10-14 11:16:36 UTC
It seems to me like pygobject's gio bindings should be releasing the appropriate global python locks before calling potentially blocking C functions such as g_file_query_info(), g_file_copy(), etc.

Not releasing the python locks means that it's impossible to run any other python threads while the synchronous operation is going on, but also that any non-python thread created by non-python code (e.g a C library creating a thread for itself, like GStreamer creating a streaming thread for decoding) might potentially be blocked by this, e.g. if it unrefs or changes objects that are also tracked by the python layer.

Arguably one should use the async functions wherever possible, but this still looks to me like a bug which should be fixed.

Not sure what's needed here - is it just a matter of wrapping C calls in pyg_begin_allow_threads; and pyg_end_allow_threads; ?
Comment 1 John Stowers 2009-01-30 07:11:37 UTC
Please see bug #569772 for a demonstration of this. I think it might actually be a dupe of this bug, but I am not sure.
Comment 2 Paul Pogonyshev 2009-01-30 17:55:07 UTC
*** Bug 569772 has been marked as a duplicate of this bug. ***
Comment 3 John Stowers 2009-01-31 22:40:17 UTC
Any chance this fix (releasing the locks) could get into the next stable release? The current limitation makes GIO effectively useless for transferring large files
Comment 4 John Stowers 2009-02-10 00:04:54 UTC
Ping? I think this a quite a serious limitation...
Comment 5 Gustavo Carneiro 2009-02-14 19:12:10 UTC
This bug is quite easy to fix; you just need to add pyg_unblock_threads() / pyg_block_threads() around the C function call that may take time to execute.  For example:

Index: gio/gio.override
===================================================================
--- gio/gio.override	(revision 1003)
+++ gio/gio.override	(working copy)
@@ -289,11 +289,13 @@
 
     pygio_notify_reference_callback(notify);
 
+    pyg_unblock_threads();
     g_drive_eject(G_DRIVE(self->obj),
 		  flags,
 		  cancellable,
 		  (GAsyncReadyCallback) async_result_callback_marshal,
 		  notify);
+    pyg_block_threads();
 
     Py_INCREF(Py_None);
     return Py_None;


For functions that are not overridden in a .override file, you need to add (unblock-threads #t) to the def, example:

Index: gio/gio.defs
===================================================================
--- gio/gio.defs	(revision 1003)
+++ gio/gio.defs	(working copy)
@@ -994,6 +994,7 @@
    "result of the operation.")
   (c-name "g_drive_eject")
   (return-type "none")
+  (unblock-threads #t)
   (parameters
     '("GMountUnmountFlags" "flags" (default "G_MOUNT_UNMOUNT_NONE"))
     '("GCancellable*" "cancellable" (null-ok) (default "NULL"))

Hope this helps.
Comment 6 Gian Mario Tagliaretti 2009-02-14 22:43:13 UTC
Created attachment 128737 [details] [review]
patch adding threads unblock

I don't know if I got them all, if some are missing let me know, or better update the patch :)
Comment 7 Paul Pogonyshev 2009-02-15 22:53:23 UTC
Gian: this is a case where any level of completeness is better than current state.  Please go ahead and commit your patch.
Comment 8 John Stowers 2009-02-15 23:05:37 UTC
I just tested this (uninstalled) using the attached test case. Im not sure if this was a bug in my setup, but the main loop is still stalled throughout the copy process. Can someone else please run the test case and see if they agree?
Comment 9 John Stowers 2009-02-15 23:08:10 UTC
Created attachment 128801 [details]
Test if main loop is blocked

Should be installed in the tests directory, and run from there. The expected output is a constant sequence of printed '.'s but instead I see nothing printed during the file_copy process - indicating that the mainloop is stalled.

See bug #569772 for another test case comparing the behaviour with GnomeVfs
Comment 10 Gian Mario Tagliaretti 2009-02-16 21:11:16 UTC
I've committed the patch but I'll leave the bug open as per John's comments.
Comment 11 John Stowers 2009-02-16 22:48:04 UTC
Were you able to see the behaviour I described when you ran the test case? It could just be a problem on my system.
Comment 12 John Stowers 2009-02-16 23:12:22 UTC
Created attachment 128873 [details]
Test if mainloop is blocked

Updated test case to only use the newly built gobject and gio. Still exhibits the same bug.

copy into tests/runtests2.py

run with

python tests/runtests2.py
Comment 13 Gustavo Carneiro 2009-02-17 11:01:36 UTC
Sorry this was my fault for giving bad information.  I was confusing pyg_block/unblock_threads with pyg_beging/end_allow_threads :P

I fixed it in trunk.  Sorry.
Comment 14 Gustavo Carneiro 2009-02-17 11:12:36 UTC
And for future reference, to support threading with wrapping blocking C APIs you should use:

...
pyg_begin_allow_threads;
call_the_c_function();
pyg_end_allow_threads;

For async callbacks, in the past there was pyg_block_threads and pyg_unblock_threads (wrapping similarly named Python C API functions).  The problem with pyg_block_threads is that it only works if the current thread does *not* already hold the python interpreter lock.

Once PEP 311 (in Python 2.3), a new API, gil_state_ensure, gil_state_release, was introduced that avoids the problem above.  So, for all intents and purposes, we could already consider block/unblock threads as deprecated.
Comment 15 John Stowers 2009-02-17 11:16:41 UTC
> Sorry this was my fault for giving bad information.  I was confusing
> pyg_block/unblock_threads with pyg_beging/end_allow_threads :P
> 
> I fixed it in trunk.  Sorry.
> 

Ok that is good to hear. Do you also need to revert the multiple addition of

+  (unblock-threads #t)

In the gio.defs file?

Any chance you could also apply this fix to the current stable branch?
Comment 16 Gustavo Carneiro 2009-02-17 11:28:39 UTC
(In reply to comment #15)
> > Sorry this was my fault for giving bad information.  I was confusing
> > pyg_block/unblock_threads with pyg_beging/end_allow_threads :P
> > 
> > I fixed it in trunk.  Sorry.
> > 
> 
> Ok that is good to hear. Do you also need to revert the multiple addition of
> 
> +  (unblock-threads #t)

No, that part is still correct.  The generated code from that is correct.

> 
> In the gio.defs file?
> 
> Any chance you could also apply this fix to the current stable branch?
> 

Not me; ask Gian? :D
Comment 17 John Stowers 2009-02-17 11:34:57 UTC
> > Ok that is good to hear. Do you also need to revert the multiple addition of
> > 
> > +  (unblock-threads #t)
> 
> No, that part is still correct.  The generated code from that is correct.

Oh OK, so it is just a matter of confusing naming.

> 
> > 
> > In the gio.defs file?
> > 
> > Any chance you could also apply this fix to the current stable branch?
> > 
> 
> Not me; ask Gian? :D
> 

Ok, I am re-opening this bug then. No offence intended.

Gian et. al please close this again if there is no possibility of applying this fix to stable branch, or if you do not intend to make any more releases from that branch (which would obviously make applying the patch pointless).
Comment 18 Gian Mario Tagliaretti 2009-02-17 22:08:52 UTC
(In reply to comment #17)

> Gian et. al please close this again if there is no possibility of applying this
> fix to stable branch, or if you do not intend to make any more releases from
> that branch (which would obviously make applying the patch pointless).

It's going to be hell but yes, I'm going to backport the bug fixes into 2.16 branch and make a new release. 

Comment 19 Gian Mario Tagliaretti 2009-02-20 22:30:02 UTC
Fixed in stable branch too.