Re: [pygtk] PyGTK deadlocks... I know, right?

2013-01-14 Thread Christian Becke

Am 12.01.2013 10:24, schrieb Niklas Koep:

Here's one. I'm using PyGTK 2.24 with gstreamer 0.10.36. Whenever gstreamer
reports an error on my playbin2's message bus I display the error in a
gtk.MessageDialog. This causes the app to deadlock unless I use a context
manager with gtk.gdk.lock. At first I suspected a threading issue, but
according to the gstreamer docs messages on the bus are emitted from the
main thread so I don't see how threading could be an issue. Nevertheless, I
verified this by retrieving the thread ids with libc via ctypes and they're
identical. Here's a minimal example of an app that demonstrates the issue:
http://pastebin.com/b4VTGy9q.

Any ideas of an obvious issue I'm overlooking? I'd greatly appreciate any
input. Cheers!


Calling gtk.Dialog.run() starts a second mainloop, which in a 
non-threaded application will block the original mainloop until it 
exits. This is useful for modal dialogs, but this is not what you want 
here. I don't know in detail what is happening in your example, but my 
guess would be that calling gtk.Dialog.run() also blocks the 
glib.MainLoop driving gstreamer, causing havoc once it continues.

Working example below.

Cheers,
Christian

#!/usr/bin/env python2

"""
$ python2 --version
Python 2.7.3

$ pkg-config pygtk-2.0 --modversion
2.24.0

$ pkg-config --modversion gstreamer-0.10
0.10.36
"""

import gst
import gtk
gtk.gdk.threads_init()
import gobject
gobject.threads_init()


def main():
bin_ = gst.element_factory_make("playbin2")
bus = bin_.get_bus()
bus.add_signal_watch()
bus.connect("message", on_message)

window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(300, 180)
window.connect("delete-event", quit, bin_)

vbox = gtk.VBox()
window.add(vbox)

button = gtk.Button("play")
button.connect("clicked", on_clicked, bin_)
vbox.pack_start(button, False)

button = gtk.Button("message")
button.connect("clicked", on_message_clicked, bin_)
vbox.pack_start(button, False)

window.show_all()

gtk.main()

def quit(window, event, bin_):
bin_.set_state(gst.STATE_NULL)
gtk.main_quit()
return False

def on_message_clicked (button, bin_):
   err = gst.GError ("test", gst.CORE_ERROR_FAILED, "test")
   msg = gst.message_new_error (bin_, err, "test error handling")
   bin_.post_message (msg)

def on_clicked(button, bin_):
bin_.set_property("uri", "file:///tmp/test.mp3")
bin_.set_state(gst.STATE_PLAYING)

def on_message(bus, message):
if message.type == gst.MESSAGE_ERROR:
err, debug = message.parse_error()

# FIXME: without the context manager destroying the dialog causes a
#deadlock, but shouldn't this lock protection be redundant?
#with gtk.gdk.lock: error_dialog("Error", "%s" % err)
error_dialog("Error", "%s" % err)

def on_response(diag, res):
   diag.destroy()

def error_dialog(text, secondary_text=""):
diag = gtk.MessageDialog(
flags=gtk.DIALOG_DESTROY_WITH_PARENT|gtk.DIALOG_MODAL,
type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK
)
diag.set_property("text", text)
diag.set_property("secondary-text", secondary_text)
diag.connect("response", on_response)
diag.show()

if __name__ == "__main__":
main()

___
pygtk mailing list   pygtk@daa.com.au
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/


Re: [pygtk] PyGTK deadlocks... I know, right?

2013-01-12 Thread Robert Schroll
First, a disclaimer:  I don't grok threads, so what I'm saying may be 
wrong.  If someone else says differently, believe them.  But I think 
I've figured out what's going on.


On 01/12/2013 06:24 AM, Niklas Koep wrote:

Here's one. I'm using PyGTK 2.24 with gstreamer 0.10.36. Whenever
gstreamer reports an error on my playbin2's message bus I display the
error in a gtk.MessageDialog. This causes the app to deadlock unless I
use a context manager with gtk.gdk.lock. At first I suspected a
threading issue, but according to the gstreamer docs messages on the bus
are emitted from the main thread so I don't see how threading could be
an issue.  Nevertheless, I verified this by retrieving the thread ids
with libc via ctypes and they're identical.


I suspect your reasoning is faulty [1], but your conclusion is correct: 
the signal handlers will be called in the main thread.  But why would 
you expect them to be called inside the GDK lock?  The whole point of 
calling threads_init, as I understand it, is to tell the main loop to 
release the lock occasionally so that you can grab it in another thread. 
 So no matter what thread you're in, you need to grab the lock when you 
need it.  (And if you're doing anything GTKish, you need it.)  The need 
for the lock in your sample program makes sense.


But do you actually need a threaded pyGTK?  GStreamer will use as many 
threads as it deems necessary completely independently of whether you 
set up threading in Python (I think).  So you can also get your sample 
program to work by taking out the two threads_init() calls as well as 
the gtk.gdk.lock.  Maybe your real program does need threads, but what 
you've shown us certainly doesn't [2].


Hope that helps,
Robert

[1] I suspect you were looking here 
(http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-bus.html), 
where it says that bus handlers will be called from the main thread. 
But you're not using those; you're using a GSignals-based approach.  The 
signal handlers will also be called from the main thread, which explains 
your results.


[2] Note that you can also write a threaded Python program, but leave 
the GTK part single-threaded.  If you take out your 
gtk.gdk.threads_init() call, you can also take out the gtk.gdk.lock. 
You can use multiple threads in Python now, but you can only do GTK 
stuff from the main thread.  This isn't actually that much of a 
restriction -- if you want to GTK stuff from a secondary thread, you 
just put that code into gobject.idle_add().  It will then be executed in 
the main thread (which always has the GDK lock in this approach) when 
there's time.  Personally, I find this way of thinking easier, but I try 
to avoid threads completely if at all possible.

___
pygtk mailing list   pygtk@daa.com.au
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/


Re: [pygtk] PyGTK deadlocks... I know, right?

2013-01-12 Thread Giuseppe Penone
of course if you open a message dialog in a single threaded app you stop
the application until the user presses on the ok button.
if you want the app to go on you need a second non graphical thread.
otherwise use the notifications:

subprocess.call("notify-send CIAO, shell=True)


On Sat, Jan 12, 2013 at 10:24 AM, Niklas Koep  wrote:

> Here's one. I'm using PyGTK 2.24 with gstreamer 0.10.36. Whenever
> gstreamer reports an error on my playbin2's message bus I display the error
> in a gtk.MessageDialog. This causes the app to deadlock unless I use a
> context manager with gtk.gdk.lock. At first I suspected a threading issue,
> but according to the gstreamer docs messages on the bus are emitted from
> the main thread so I don't see how threading could be an issue.
> Nevertheless, I verified this by retrieving the thread ids with libc via
> ctypes and they're identical. Here's a minimal example of an app that
> demonstrates the issue: http://pastebin.com/b4VTGy9q.
>
> Any ideas of an obvious issue I'm overlooking? I'd greatly appreciate any
> input. Cheers!
>
> ___
> pygtk mailing list   pygtk@daa.com.au
> http://www.daa.com.au/mailman/listinfo/pygtk
> Read the PyGTK FAQ: http://faq.pygtk.org/
>
___
pygtk mailing list   pygtk@daa.com.au
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/

[pygtk] PyGTK deadlocks... I know, right?

2013-01-12 Thread Niklas Koep
Here's one. I'm using PyGTK 2.24 with gstreamer 0.10.36. Whenever gstreamer
reports an error on my playbin2's message bus I display the error in a
gtk.MessageDialog. This causes the app to deadlock unless I use a context
manager with gtk.gdk.lock. At first I suspected a threading issue, but
according to the gstreamer docs messages on the bus are emitted from the
main thread so I don't see how threading could be an issue. Nevertheless, I
verified this by retrieving the thread ids with libc via ctypes and they're
identical. Here's a minimal example of an app that demonstrates the issue:
http://pastebin.com/b4VTGy9q.

Any ideas of an obvious issue I'm overlooking? I'd greatly appreciate any
input. Cheers!
___
pygtk mailing list   pygtk@daa.com.au
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/