I'm creating GUI using gtk3. So that the GUI and operation works together, I make a thread with this code: threading.Thread(target=function).start()
. Without threading, everything works well, but the GUI will be freezed. With threading, this error occured:
The first one is Segmentation fault (core dumped)
The second one is *** glibc detected *** python: double free or corruption (!prev): 0x09154320 ***
The third one is Gtk:ERROR:/build/buildd/gtk+3.0-3.4.2/./gtk/gtktextview.c:3726:gtk_text_view_validate_onscreen: assertion failed: (priv->onscreen_validated) Aborted (core dumped)
Do you know why did that happens?
EDIT: my code:
GUI.py
from gi.repository import Gtk, Gdk, GLib
import Process
import gobject
import threading
class gui():
def __init__(self):
self.window = Gtk.Window()
self.window.connect('delete-event', Gtk.main_quit)
self.box = Gtk.Box()
self.window.add(self.box)
self.label = Gtk.Label('idle')
self.box.pack_start(self.label, True, True, 0)
self.progressbar = Gtk.ProgressBar()
self.box.pack_start(self.progressbar, True, True, 0)
self.button = Gtk.Button(label='Start')
self.button.connect('clicked', self.on_button_clicked)
self.box.pack_start(self.button, True, True, 0)
self.window.show_all()
GLib.threads_init()
Gdk.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
def working1(self):
self.label.set_text('working1')
result = Process.heavyworks1()
print result
self.label.set_text('idle')
def on_button_clicked(self, widget):
threading.Thread(target=self.working1).start()
if __name__ == '__main__':
gui = gui()
Process.py
a = 0 x = 'something'
def heavyworks1():
#global a
#doing something
#doing other thing
#a = something
#return result
def heavyworks2(param):
#doing something
#doing other thing
#return result
I've resolved this one. What you need to do is FULLY SEPARATE ANY GTK CALL FROM ANY THREAD.
Those error occured because there were still some code accessing gtk ui from worker thread (thread that doing my calculation in the background). What I need to do is just separate ALL gtk call from thread by using gobject.idle_add(some_fuction_telling_gtk_what_to_do)
This is a sample:
def stop_progress(self):
self.worker.join()
self.label.set_text('idle')
def working_thread(self, num):
self.textview.set_text(num)
Process.heavyworks2(num)
gobject.idle_add(self.stop_progress)
self.worker = threading.Thread(target=self.working_thread, args=[100000])
self.worker.start()
You see from that code a function that suppose to working in the background (working_thread(self,num)
) still having a line accessing gtk call (self.textview.set_text(num)
). Separate that code into a function and call it from your thread using gobject.idle_add(gtk_call_function)
.
It's become like this.
def stop_progress(self):
self.worker.join()
self.label.set_text('idle')
def updateTextView(self, num):
self.textview.set_text(num)
def working_thread(self, num):
gobject.idle_add(self.updateTextView, num)
Process.heavyworks2(num)
gobject.idle_add(self.stop_progress)
self.worker = threading.Thread(target=self.working_thread, args=[100000])
self.worker.start()
So, one important point here is don't update gtk ui directly from any thread. Just separate every code accessing gtk into a function and call it by gobject.idle_add()
from thread.
Perhaps you have to do this first:
import gobject
gobject.threads_init()
Does that keep it from crashing? (Check out http://faq.pygtk.org/index.py?req=show&file=faq20.006.htp)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With