Open phil294 opened 1 year ago
Aha! Solvable by maintaining a separate btn_refs = [] of Gtk::Button
and keeping a ref of all buttons in there (btn_refs << btn
).
Surely this is just a hacky workaround...?
I've now also learned it is important to call GC manually once after destroying windows:
window.destroy
GC.collect
window = nil
If I don't do this, the GC runs at a later point in time, tries to run Window.finalize
, but because the main window reference is gone, things run out of control. At least that's what I think is going on, based on stack traces like this one:
Invalid memory access (signal 11) at address 0x0
[0x556ccaf8e0a6] *Exception::CallStack::print_backtrace:Nil +118 in bin/ahk_x11
[0x556ccaf66a86] ~procProc(Int32, Pointer(LibC::SiginfoT), Pointer(Void), Nil) +310 in bin/ahk_x11
?
#0 0x0000556ccaf8e0b5 in print_backtrace () at /usr/lib/crystal/exception/call_stack/libunwind.cr:103
#1 0x0000556ccaf66a86 in -> () at /usr/lib/crystal/signal.cr:151
#2 0x00007f33f1184a00 in <signal handler called> () at /usr/lib/libc.so.6
#3 0x00007f33f1c10947 in () at /usr/lib/libgobject-2.0.so.0
#4 0x00007f33f1c00f75 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#5 0x00007f33f1c01204 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#6 0x00007f33f231f35e in () at /usr/lib/libgtk-3.so.0
#7 0x00007f33f232eec1 in () at /usr/lib/libgtk-3.so.0
#8 0x00007f33f1bf1104 in g_object_unref () at /usr/lib/libgobject-2.0.so.0
#9 0x0000556ccb10db5a in finalize () at /b/ahk_x11/lib/gobject/src/gtk/gobject-cache-gtk.cr:18657
#10 0x0000556ccaf73732 in -> () at /usr/lib/crystal/gc/boehm.cr:193
#11 0x00007f33f13b523f in GC_invoke_finalizers () at /usr/lib/libgc.so.1
#12 0x00007f33f13b546e in () at /usr/lib/libgc.so.1
#13 0x00007f33f13bf713 in GC_generic_malloc_many () at /usr/lib/libgc.so.1
#14 0x00007f33f13cdf6e in GC_malloc_kind () at /usr/lib/libgc.so.1
#15 0x0000556ccafe2776 in malloc () at /usr/lib/crystal/gc/boehm.cr:129
#16 0x0000556ccaf4353e in __crystal_malloc64 () at /usr/lib/crystal/gc.cr:24
#17 0x0000556ccb1c9ffb in new () at /usr/lib/crystal/channel.cr:101
#18 0x0000556ccb19df7b in create_context_and_wait () at /usr/lib/crystal/channel.cr:46
#19 0x0000556ccb1c48fb in select_impl () at /usr/lib/crystal/channel.cr:457
#20 0x0000556ccb1c36f6 in select () at /usr/lib/crystal/channel.cr:408
#21 0x0000556ccb1603d1 in clock () at /b/ahk_x11/src/run/runner.cr:127
#22 0x0000556ccaf70319 in -> () at /b/ahk_x11/src/run/runner.cr:87
#23 0x0000556ccb01cc62 in run () at /usr/lib/crystal/fiber.cr:146
#24 0x0000556ccaf665a6 in -> () at /usr/lib/crystal/fiber.cr:98
#25 0x0000000000000000 in ()
with /gobject-cache-gtk.cr:18657
being Gtk::Window.finalize
.
The same necessity applies to widgets:
window.destroy
widgets.each &.destroy
GC.collect
window = nil
widgets = nil
GC.collect
Just a few more crashes to solve...
It worked with GTK4 bindings.
require "gtk4"
app = Gtk::Application.new("hello.example.com", Gio::ApplicationFlags::None)
app.activate_signal.connect do
window = Gtk::ApplicationWindow.new(app)
fixed = Gtk::Fixed.new
50.times do |i|
20.times do |j|
btn = Gtk::Button.new label: i.to_s+"/"+j.to_s
fixed.put btn, i*10, j*10
end
end
window.child = fixed
window.present
end
exit(app.run)
Interesting, thanks. This speaks in favor of the approach taken by your GI Crystal shard 👍
I can't really use Gtk 4 though, as I need cross-distro binaries with as much long-lasting compatibility as possible (issue). I'd probably do it if I could statically link gtk4 somehow
Edit: I've now switched from this shard to https://github.com/phil294/gtk3.cr instead where I am facing less issues
Hello,
consider this demo code which simply adds 100 buttons:
Expected:
Actual:
![img](https://waritschlager.de/share/30F0AA48DED7CA793632FCD5591A61B4.png)
Bug only appears with GC active (default).
In this case, GC starts killing off widgets every ~130 widget additions or so. This bug can also appear much faster, however. I am building AHK_X11, AutoHotkey for Linux, a scripting language. When I translate the above Crystal code into AHK, widgets are disappearing even after 3-20 widgets have been placed. I will add a demo code snippet + GIF below. Its internals aren't important I assume (because there is a lot of other stuff going on too in the background which probably affects GC behavior), I only want to show this to somewhat prove the severity of this bug: It definitely occurs with only a few buttons as well.
Same behavior with CheckButtons. Did not observe such behavior with ComboBoxes or Labels.
Did not investigate much further than all of this. I will gladly provide more input as needed, however. Any idea on how to at least circumvent this bug (other than
-Dgc_none
, of course) would be much appreciated, as this is kind of a blocker for me now.On a related note, I am seeing a few different GLib null pointers (exceptions) and invalid memory access errors (process abort) then and again. For example, the above GIF window crashed (it always does at some point). Those appear seemlingly random, so I guess they are GC-related too, but I haven't tested this yet, and it's not a show stopper. I also cannot use
malloc_pthread_shim
because I am using-Dpreview_mt
which does not seem to work together. Might need to open up new issue(s) at some point.Thank you once again for all your work on this!