Ticket #1181 (new defect)

Opened 8 years ago

Last modified 6 years ago

Filling a TreeView from a background thread

Reported by: guest Owned by: somebody
Priority: normal Milestone: 0.10.1
Component: general (Gtk+, Glib) Version: 0.10.1
Keywords: Cc: marc.lisp@…



I try to refresh the content from a TreeView? from a background thread

(created by forkIO). Basically from the background thread I call listStoreClear and several listStoreAppend from the background thread. I also use the code from 'Real world Haskell' timeoutAddFull (yield >> return True)

priorityDefaultIdle 50

So that UI call's has a effect from the background, if I update the text of a label from the background thread this seems to work however for my treeview I get the error : << There is a disparity between the internal view of the GtkTreeView?, and the GtkTreeModel?. This generally means that the model has changed without letting the view know. Any display from now on is likely to be incorrect.

(Newsreader:31777): Gtk-CRITICAL **: gtk_tree_model_sort_convert_iter_to_child_iter: assertion `VALID_ITER (sorted_iter, tree_model_sort)' failed

(Newsreader:31777): Gtk-CRITICAL **: gtk_tree_model_sort_convert_iter_to_child_iter: assertion `VALID_ITER (sorted_iter, tree_model_sort)' failed Newsreader: user error (ListStore?.getRow: iter does not refer to a valid entry)

Apparently I do something wrong, so how do you update a TreeView? from a background thread (in C# or Java we must do the update on the thread of the UI but I do not seem to find a function to do this.

Any help is really appreciated.


Marc Mertens

Change History

Changed 7 years ago by axel

This could be a real bug in our code.

In case it is not:

If you do not compile your program with -threaded (which you seem to do, otherwise you wouldn't need the idle handler), then you are adding elements from the same OS thread as Gtk+ runs in: it's the only thread there exists in the program. So this is not a concurrency problem but rather a problem with the way TreeIters? are handled.

In case you use -threaded, you have to use postGUIAsync in Graphics.UI.Gtk.General to execute something in the Gtk+ OS thread. But I don't think this is your problem. If you had a concurrency problem by accessing Gtk+ from several threads, you could/would see a segfault or an odd warning from Xlib.

Changed 6 years ago by guest

This may be related to


because it shares the "Any display from now on is likely to be incorrect." message. we don't use "-threaded".

Changed 6 years ago by duncan

I have a sneaking suspicion that the problem is that we need to invalidate all iterators when deleting elements from the list store. I can reproduce this bug relatively easily using ThreadScope? so I will attempt to confirm my suspicion.

Changed 6 years ago by duncan

Ok, my suspicion was wrong, but I have other evidence.

In my case at least, what is happening is that C calls us via gtk2hs_store_get_iter, we call into Haskell land via gtk2hs_store_get_iter_impl. What normally happens next is that gtk2hs_store_get_iter_impl returns and then gtk2hs_store_get_iter returns.

However in the cases where things go horribly wrong, after the call into gtk2hs_store_get_iter_impl, instead of it returning, we see other calls coming from C land, e.g. gtk2hs_store_ref_node. What is going on? Well, on the Haskell side we must have switched thread, and that thread must have called back into C, so that gtk+ then calls us back again. So we've re-entered the GtkTreeView code, which is certainly not expecting it. When the original gtk2hs_store_get_iter finally returns, the GtkTreeView data structures get corrupted and bad things ensue, usually a segfault, but sometimes an assertion failure in some GtkTreeView? C file.

So the root of the problem seems to be re-entering Gtk+ functions while in the middle of a GtkTreeView asking us some detail of our model/store.

How can we avoid the thread switching and re-entering... not sure yet.

Note: See TracTickets for help on using tickets.