Xpra: Ticket #420: Xpra does not hold the gtk global mutex while calling into gtk

Xpra 0.8.8 on FreeBSD crashes on startup with an error from pthread_mutex_unlock (ports/177800).

The gtk documentation on threads says:

GTK+ is "thread aware" but not thread safe — it provides a global lock controlled by gdk_threads_enter()/gdk_threads_leave() which protects all use of GTK+. That is, only one thread can use GTK+ at any given time.

However I can't find any use of gdk_threads_enter() or gdk_threads_leave() within Xpra's source.

This crash on FreeBSD is caused by g_thread_abort()).

Xpra works on Linux since Linux (apparently?) returns 0 in the case of unlocking an unlocked mutex, and as far as I'm aware, POSIX leaves this as undefined behavior (http://stackoverflow.com/a/1778821).

Applying the obvious patch (https://gist.github.com/thefloweringash/6302597) allows Xpra to start and accept an xterm, but I haven't yet been able to attach due to a socket.error (Socket is not connected), which I'm assuming is unrelated.



Thu, 22 Aug 2013 02:50:39 GMT - Antoine Martin:

You do not need gdk_threads_enter() / gdk_threads_leave() if your application only accesses GTK from the UI thread. This is what xpra does unless proven otherwise. You never need to add those calls around gtk.main, for sure.


Looks to me like something is broken on your build (GTK? Python?). Please try the latest releases, 0.8.x is not supported, and even 0.9.x is unlikely to get another update, so you should be testing with 0.10.1 or later (trunk).


Thu, 22 Aug 2013 03:02:04 GMT - thefloweringash:

The gtk examples in the threads page do wrap gtk_main() with gtk_threads_enter()/gtk_threads_leave(), and though I can't quickly find anything definitive on the subject, this post turned up by a quick google seems to agree with my analysis.

http://blogs.operationaldynamics.com/andrew/software/gnome-desktop/gtk-thread-awareness

I tested with 0.8.8 since I defaulted to the version in ports. I'll test 0.10.1.


Thu, 22 Aug 2013 03:37:07 GMT - Antoine Martin:

For more information on how xpra uses the UI thread, see:

Note the absence of enter/leave anywhere.

Now it is possible that there is some code somewhere that improperly calls some gtk ui code from a non-main thread, if that is the case we really want to hunt it down and fix it, you should be able to get a backtrace for us using gdb.

What can be misleading on threading with (py)gtk is posts like this one: Multi-threaded GTK applications – Part 1: Misconceptions which state: It turns out that you’re supposed to put gdk_threads_enter()/leave() around the call you make to gtk_main(). - that is only true if you intend to use threading (multiple threads modifying the UI) - which is not our case (for the reasons explained above).

Please also note: no matter if you are doing PyGTK calls from a separate thread or not, you must compile PyGTK with --enable-threads - I assume this is your case (I would have expected the enter/leave calls to error out if it was not the case)


Thu, 22 Aug 2013 04:28:25 GMT - thefloweringash:

gdb session of xpra 0.10.1 https://gist.github.com/thefloweringash/6303230

EDIT: a gdb session for the following simplified version https://gist.github.com/thefloweringash/6303264

#!/usr/local/bin/python2.7
import gtk.gdk
gtk.gdk.threads_init()
gtk.main()

Thu, 22 Aug 2013 04:48:59 GMT - Antoine Martin: status changed; resolution set

Then the problem is with FreeBSD, this code is valid and can be found in many applications, including the textbook examples from the pygtk FAQ linked above.


Fri, 23 Aug 2013 05:29:08 GMT - thefloweringash:

Short version

FreeBSD compatibility for 0.10.1 is a very small patch: https://gist.github.com/thefloweringash/6315767. Since 0.8.8, most of the gtk.gdk.threads_init() calls have been changed to the more precise glib.threads_init() (formerly gobject.threads_init()). After applying this change to server.py I can successfully interact with an xterm over xpra.

Long version

After investigating further I have to disagree. The PyGTK samples run without aborting on FreeBSD, and I find none of the posts linked to be in error. I do not believe the code sample in #comment:4 is valid. At the risk of being overly verbose, I hope a somewhat thorough exploration might still be generally useful, since there seems to be some disagreement on this topic.

I propose the following condition:

or for the sake of avoiding ambiguity, in pygtk terms

It is important to note that glib.threads_init() (docs) corresponds to g_thread_init(), and does not call gdk_threads_init(). That is, it is enabling glib thread safety, and not engaging the gtk global mutex.

In the demoed on the mailing list also satisfies the condition the as it both calls gtk.gdk.threads_init() and wraps gtk.main() with gtk.gdk.threads_enter() and gtk.gdk.threads_leave().

The "comments for g_mutex_unlock() make it quite explicitly undefined behavior.


Fri, 23 Aug 2013 09:25:23 GMT - Antoine Martin:

Thanks for the details and the patches.

The straightforward build fixes are merged in r4216 and I will apply them to the 0.10.x branch before the next point release.

The threading patch was merged in r4217, I am hoping this one will get more testing on a variety of platforms (especially win32 which has had problems in the past) before I apply to 0.10.x - this sort of change makes me nervous.

(I have briefly read the links and it looks like you are right about enter/leave being needed once we call gtk.gdk.threads_init())


Sun, 24 Nov 2013 12:07:47 GMT - Antoine Martin:

r4790 is required to prevent a server crash on OpenBSD (and probably FreeBSD and others too) - will backport to v0.10.x.


Mon, 25 Nov 2013 11:12:37 GMT - Antoine Martin:


All backported to v0.10.x in r4799


Tue, 26 Nov 2013 12:22:09 GMT - Antoine Martin: status changed; resolution deleted

Re-opening so I can change the resolution: this bug was *not* invalid.


Tue, 26 Nov 2013 12:22:17 GMT - Antoine Martin: status changed; resolution set


Sat, 04 Jan 2014 12:11:59 GMT - Antoine Martin:

Damn: this caused a regression, see #485


Wed, 15 Jan 2014 15:50:34 GMT - Antoine Martin:

And yet another one: #497

So. Much. Pain.


Sat, 23 Jan 2021 04:54:55 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/420