Gaurav
Gaurav

Reputation: 135

Gtk crashes on adding and removing listboxrows

I want to create a Gtk program that requires to continuously update a ListBox, i.e. add and remove rows. I am trying this approach. It could be cleaner but here it is just long enough to explain the problem.

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from time import sleep
from threading import Thread

def add_widgets(listbox):

    # add 5 rows
    for _ in range(5):
        for _ in range(5):
            add_row(listbox)
        window.show_all()  # make the changes visible
        sleep(1)  # to make the change stay

        # remove all the rows
        for row in listbox.get_children():
            listbox.remove(row)
        window.show_all()
        sleep(1)
    
    # all the addition and removal done
    print('finished')

def add_row(listbox):
    listboxrow = Gtk.ListBoxRow()
    label = Gtk.Label()
    label.set_text("Hey There")
    listboxrow.add(label)
    listbox.add(listboxrow)

window = Gtk.Window()
window.connect('destroy', Gtk.main_quit)
listbox = Gtk.ListBox()
window.add(listbox)
window.show_all()

# Thread to add and remove rows
update_thread = Thread(target=add_widgets, args=(listbox, ))
update_thread.start()

Gtk.main()

This code runs fine like 50% of the time. For the rest, it gives me 3 types of errors, all of them randomly.

  1. The good old SegFault after like 2 or 3 iteration of the parent loop in add_widgets
  2. The following:
**
Gtk:ERROR:../gtk/gtk/gtkcssnode.c:319:lookup_in_global_parent_cache: assertion failed: (node->cache == NULL)
Bail out! Gtk:ERROR:../gtk/gtk/gtkcssnode.c:319:lookup_in_global_parent_cache: assertion failed: (node->cache == NULL)
Aborted
  1. The last one doesn't crash the program but it adds random number of rows instead. i.e. it adds 3(random) rows instead of 5, as specified or maybe no rows at all.

I've tried adding more sleep statements at appropriate places because initially, I thought, it could be because the windows are not ready when updating widgets.

I wanna know why its happening and how can I fix it.

EDIT: It's probably something to do with the UI and the thread synchronization because, it(the crash) happens more frequently when interacting with the window. For instance, when you are dragging it, it has more chances of crashing.

Upvotes: 1

Views: 609

Answers (1)

ekalin
ekalin

Reputation: 1012

You must not call GTK+ code from other threads. All interactions must be done in the main thread. This is documented in https://developer.gnome.org/gdk3/stable/gdk3-Threads.html.

If you want to do some "background" updates of your widgets, you can simulate that with functions such as g_idle_add() (https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-idle-add), g_timeout_add() (https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-timeout-add) and other related functions.

Upvotes: 3

Related Questions