hugopl / gtk4.cr

GTK4 bindings for Crystal
https://hugopl.github.io/gtk4.cr/
MIT License
102 stars 8 forks source link

`Gtk::Snapshot#append_texture` crashes program with SIGSEGV #27

Closed BlobCodes closed 2 years ago

BlobCodes commented 2 years ago

The following code:

require "gtk4"

snapshot = Gtk::Snapshot.new
texture = Gdk::Texture.new_from_filename("/path/to/some/image.ext")
snapshot.append_texture(texture, Graphene::Rect.zero)

Causes the program to crash with the following message:

Invalid memory access (signal 11) at address 0xffffffffffffff98
[0x4b71b6] *Exception::CallStack::print_backtrace:Nil +118 in /var/home/blobcodes/.cache/crystal/crystal-run-test2.tmp
[0x49524a] ~procProc(Int32, Pointer(LibC::SiginfoT), Pointer(Void), Nil) +330 in /var/home/blobcodes/.cache/crystal/crystal-run-test2.tmp
[0x7f608dd6dac0] ?? +140052673256128 in /lib64/libc.so.6
[0x7f608e4bbc9e] ?? +140052680916126 in /lib64/libgtk-4.so.1
[0x7f608e4bd0cb] gtk_snapshot_append_texture +155 in /lib64/libgtk-4.so.1
[0x550de2] *Gtk::Snapshot#append_texture<Gdk::Texture+, Graphene::Rect>:Nil +18 in /var/home/blobcodes/.cache/crystal/crystal-run-test2.tmp
[0x479e47] __crystal_main +1335 in /var/home/blobcodes/.cache/crystal/crystal-run-test2.tmp
[0x554c86] *Crystal::main_user_code<Int32, Pointer(Pointer(UInt8))>:Nil +6 in /var/home/blobcodes/.cache/crystal/crystal-run-test2.tmp
[0x554bd9] *Crystal::main<Int32, Pointer(Pointer(UInt8))>:Int32 +41 in /var/home/blobcodes/.cache/crystal/crystal-run-test2.tmp
[0x487486] main +6 in /var/home/blobcodes/.cache/crystal/crystal-run-test2.tmp
[0x7f608dd58590] ?? +140052673168784 in /lib64/libc.so.6
[0x7f608dd58649] __libc_start_main +137 in /lib64/libc.so.6
[0x479845] _start +37 in /var/home/blobcodes/.cache/crystal/crystal-run-test2.tmp
[0x0] ???

This used to work in an older version of GI-Crystal.

GI-Crystal version: 0.12.0 Crystal version: 1.4.1

hugopl commented 2 years ago

Do you remember on what version it used to work? So will be easy to find what changed.

BlobCodes commented 2 years ago

I just tried all recent commits:

BlobCodes commented 2 years ago

Also, the code I posted with the issue doesn't actually work (needs to be wrapped in a Gtk;:Application#activate_signal).

Here's working code:

require "gtk4"

app = Gtk::Application.new("test.test", :flags_none)
app.activate_signal.connect do
  rect = Graphene::Rect.zero
  snapshot = Gtk::Snapshot.new
  texture = Gdk::Texture.new_from_filename("/path/to/image.ext")
  snapshot.append_texture(texture, rect)
end
app.run
hugopl commented 2 years ago

Interesting, because running ./bin/compare-api v0.9.0 v0.10.0 shows no difference in graphene-1.0/rect.cr, so it needs more investigation... :thinking:

hugopl commented 2 years ago

I get a:

$ crystal run snapshot.cr 
**
Gtk:ERROR:../gtk/gtk/gtksnapshot.c:237:gtk_snapshot_get_current_state: assertion failed: (size > 0)
Bail out! Gtk:ERROR:../gtk/gtk/gtksnapshot.c:237:gtk_snapshot_get_current_state: assertion failed: (size > 0)
Program received and didn't handle signal IOT (6)

Errror when running this with a png file.

BlobCodes commented 2 years ago

I just generated gtk from the two commits mentioned above. In all the relevant files, the only change was this:

@@ -43,20 +43,6 @@ module Gtk
       LibGtk.gtk_snapshot_get_type
     end

-    # Creates a new `GtkSnapshot`.
-    def initialize
-      # gtk_snapshot_new: (Constructor)
-      # Returns: (transfer full)
-
-      # C call
-      _retval = LibGtk.gtk_snapshot_new
-
-      # Return value handling
-
-      @pointer = _retval
-      LibGObject.g_object_set_qdata(_retval, GICrystal::INSTANCE_QDATA_KEY, Pointer(Void).new(object_id))
-    end
-
     # Appends a stroked border rectangle inside the given @outline.
     #
     # The four sides of the border can have different widths and colors.

..so I went to the GTK git repo to find out how gtk_snapshot_new is defined:

https://github.com/GNOME/gtk/blob/8fccfc7a3d77914eae8ac8f8dd68f1f69522612a/gtk/gtksnapshot.c#L273-L296

/**
 * gtk_snapshot_new:
 *
 * Creates a new `GtkSnapshot`.
 *
 * Returns: a newly-allocated `GtkSnapshot`
 */
GtkSnapshot *
gtk_snapshot_new (void)
{
  GtkSnapshot *snapshot;

  snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);

  gtk_snapshot_states_init (&snapshot->state_stack);
  gtk_snapshot_nodes_init (&snapshot->nodes);

  gtk_snapshot_push_state (snapshot,
                           NULL,
                           gtk_snapshot_collect_default,
                           NULL);

  return snapshot;
}

It turns out the function gtk_snapshot_new does a lot more than just g_object_new. I think the commit mentioned above should be partially reverted - constructors with empty params should be generated.