Tags

employment
llc
xrp
redhat
ripple
interfaces
ncurses
ruby
refs
filesystems
retro gaming
raspberry pi
sinatra
3d printing
nethack
gcc
compiler
fedora
virtfs
project
gaming
vim
grep
sed
aikido
philosophy
splix
android
lvm
storage
bitcoin
projects
sig315
miq
db
polisher
meditation
hopex
conferences
omega
simulator
bundler_ext
rubygems
book review
google code in
isitfedoraruby
svn
gsoc
design patters
jsonrpc
rjr
aeolus
ohiolinuxfest
rome
europe
travel
brno
gtk
python
puppet
conference
fudcon
html5
snap
tips
ssh
linux
hardware
libvirt
virtualization
engineering expo
cloud
redmine
plugins
rpm
yum
rake
screencasting
jruby
fosscon
pidgin
gnome-shell
distros
notacon
presentation
rails
deltacloud
apache
qmf
passenger
syrlug
hackerspace
music
massive attack
backups
crypto
vnc
xsd
rxsd
x3d
mercurial
webdev
ovirt
qpid
haikus
poetry
legaleese
jquery
selenium
testing
xpath
git
sshfs
svg
ldap
autotools
pygtk
xmlrpc
slackware

Dec 5 2007 pygtk

pyGTK and Threading

I am in the process of adding a gnome gui interface to my soon-to-be released project. Incorporating Python, GTK, and Glade, I’ve run into several quirky issues relating to running threads and sharing access to GTK widgets. Often I will see a worker thread hanging until the window is closed, at which point it resumes operation, or a more serious error:

Gtk-ERROR **: file gtktextlayout.c: line 1990 (gtk_text_layout_get_line_display): should not be reached

which indicates an illegal cross-thread boundary violation.

After much searching, I found this site which fills in the story concerning pyGTK and threading very nicely.

First lets import the threading and gtk libraries we need:

import threading
try:
   import pygtk
   pygtk.require("2.0")
except:
try:
   import gtk
   import gtk.glade
except:
   sys.exit(1)

Next lets create a class which will be responsible for loading a window created in glade and operating on it

class MyWindow:
    def init(self):
        self.wTree = gtk.glade.XML('foofile.glade', 'mywindow')
        dic = { 'onbuttonclick' : self.buttonclick }
        self.wTree.signalauto_connect(dic)

def button_click(self, widget):
    # create worker thread
    threading.Thread(target=self.run).start()

# running in worker thread def run(self): self.wTree.getwidget(‘widgetname’).do_something()

The problem is the worker thread is trying to access the gtk widget created in the original thread, which throws the aforementioned exception. Luckily we can easily instruct python to pop into a gtk created thread, and then run the code, which does not result in the boundry violation. This is done easily by surrounding the widget access call with:

 gtk.gdk.threadsenter()
 self.wTree.getwidget('widgetname').dosomething()
 gtk.gdk.threads_leave()

Of course, for this to work, gtk will need to initialize its threading system, which you must explicitly do before you invoke gtk main:

if name == "main":
    hwg = MyWindow()
    gtk.gdk.threads_init()
    gtk.main()

Of course this is a simple example, but you so long as you initialize the gtk threading system, and pop into gtk threads before accessing / operating on widgets, you should have no problems with threading.