jhass / crystal-gobject

gobject-introspection for Crystal
BSD 3-Clause "New" or "Revised" License
127 stars 13 forks source link

Gtk + Multithreading #106

Closed phil294 closed 1 year ago

phil294 commented 1 year ago

Sorry for all these issues... but I think this one is quite different from my previous one, as it has nothing to do with GC:

require "gobject/gtk/autorun"
spawn do
  loop do |i|
    window = Gtk::Window.new
    window.show_all
    window.destroy
    puts 1
  end
end

run with MT, and GC disabled to make sure these aren't gc problems:

crystal build -Dpreview_mt -Dgc_none test.cr

This usually runs fine for a few iterations (something between 0 and 200 times). Alongside it may output Gtk-Warnings. Eventually it crashes, for example like this:

$ ./test
1
1
1
1
1
1
1
1
1
1

(test:615490): Gtk-CRITICAL **: 02:55:22.225: gtk_widget_get_toplevel: assertion 'GTK_IS_WIDGET (widget)' failed

(test:615490): Gtk-CRITICAL **: 02:55:22.225: _gtk_widget_captured_event: assertion 'WIDGET_REALIZED_FOR_EVENT (widget, event)' failed
1
1
(test:615490): GLib-GObject-CRITICAL **: 02:55:22.243: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed

(test:615490): GLib-GObject-CRITICAL **: 02:55:22.243: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
1
1
1
1
1
Invalid memory access (signal 11) at address 0x8
1
[0x55eae2265da6] *Exception::CallStack::print_backtrace:Nil +118 in ./test
[0x55eae2255546] ~procProc(Int32, Pointer(LibC::SiginfoT), Pointer(Void), Nil) +310 in ./test
[0x7f46fd6dba00] ?? +139942876264960 in /usr/lib/libc.so.6
[0x7f46fda600f6] ?? +139942879953142 in /usr/lib/libglib-2.0.so.0
[0x7f46fda60516] g_slice_free1 +438 in /usr/lib/libglib-2.0.so.0
[0x7f46f967d260] ?? +139942808769120 in /usr/lib/gtk-3.0/modules/libcanberra-gtk-module.so
[0x7f46fd5ce6ae] ?? +139942875162286 in /usr/lib/libgdk-3.so.0
[0x7f46fda4087b] g_main_context_dispatch +411 in /usr/lib/libglib-2.0.so.0
[0x7f46fda97279] ?? +139942880178809 in /usr/lib/libglib-2.0.so.0
[0x7f46fda3fddf] g_main_loop_run +111 in /usr/lib/libglib-2.0.so.0
[0x7f46fdd63e9f] gtk_main +159 in /usr/lib/libgtk-3.so.0
[0x55eae22557bb] main +91 in ./test
[0x7f46fd6c6290] ?? +139942876177040 in /usr/lib/libc.so.6
[0x7f46fd6c634a] __libc_start_main +138 in /usr/lib/libc.so.6
[0x55eae223a565] _start +37 in ./test
[0x0] ???
`trap' para punto de parada/seguimiento (`core' generado)

Now obviously, preview_mt implies that multi-threading is an experimental feature, so I shouldn't get my hopes up high. However, crystal-gobject + preview_mt DO work great together, most of the time! It's just that when you run a lot of code with it, at some point things will fail.

So I wanted to share this experience, hoping that someone has an idea. :-)

hugopl commented 1 year ago

All UI rendering in GTK must happen in the same thread of the main loop, you can do stuff in other threads... but need to update the UI always in the same mainloop thread.

So usually you do stuff in some thread and update the UI in the callback of GLib.idle_add.

phil294 commented 1 year ago

oh my, you're right. Thanks @hugopl, and sorry about that.

I thought I had trimmed down some errors I was seeing to the smallest possible reproduction case, but I forgot to use idle_add along the way, so this issue is nonsense.