lgi-devs / lgi

Dynamic Lua binding to GObject libraries using GObject-Introspection
MIT License
440 stars 70 forks source link

GtkContainer.child SIGSEGVs on access #292

Open DirtYiCE opened 2 years ago

DirtYiCE commented 2 years ago

I've tried to create a toy program, but it looks like as soon as I try to access a container's child property, it crashes.

$ lua -e 'print(require("lgi").Gtk.Window{}.child)'
Segmentation fault

Here's a gdb backtrace:

#0  0x00007ffff7fb7213 in lgi_object_2lua (L=L@entry=0x5555555872a0, obj=0x5555557b22d0, own=own@entry=0, no_sink=no_sink@entry=0) at object.c:357
#1  0x00007ffff7fb4f27 in lgi_marshal_2lua (L=0x5555555872a0, ti=0x55555569a1e0, ai=0x0, dir=GI_DIRECTION_OUT, transfer=<optimized out>, source=0x5555557a90a0, parent=1, ci=0x5555556854f0, args=0x5555557a9020) at marshal.c:1327
#2  0x00007ffff7fb6042 in lgi_marshal_field (L=0x5555555872a0, object=0x5555557a9020, getmode=1, parent_arg=1, field_arg=<optimized out>, val_arg=3) at marshal.c:1522
#3  0x0000555555560fff in luaD_precall (L=L@entry=0x5555555872a0, func=<optimized out>, func@entry=0x55555577b170, nresults=nresults@entry=-1) at ldo.c:320
#4  0x000055555556b6ef in luaV_execute (L=L@entry=0x5555555872a0, nexeccalls=nexeccalls@entry=1) at lvm.c:612
#5  0x00005555555616e5 in luaD_call (L=L@entry=0x5555555872a0, func=0x55555577b0f0, nResults=nResults@entry=1) at ldo.c:378
#6  0x000055555555e9c5 in lua_call (L=L@entry=0x5555555872a0, nargs=nargs@entry=3, nresults=nresults@entry=1) at lapi.c:782
#7  0x00007ffff7fb6480 in lgi_marshal_access (L=0x5555555872a0, getmode=1, compound_arg=1, element_arg=2, val_arg=3) at marshal.c:1547
#8  0x0000555555560fff in luaD_precall (L=L@entry=0x5555555872a0, func=<optimized out>, func@entry=0x55555577b0b0, nresults=1) at ldo.c:320
#9  0x00005555555616b4 in luaD_call (L=L@entry=0x5555555872a0, func=0x55555577b0b0, nResults=nResults@entry=1) at ldo.c:377
#10 0x0000555555569cf8 in callTMres (L=L@entry=0x5555555872a0, res=res@entry=0x55555577b090, p1=<optimized out>, p2=<optimized out>, f=<optimized out>, f=<optimized out>) at lvm.c:88
#11 0x000055555556a26e in luaV_gettable (L=L@entry=0x5555555872a0, t=<optimized out>, key=<optimized out>, val=val@entry=0x55555577b090) at lvm.c:125
#12 0x000055555556b00f in luaV_execute (L=L@entry=0x5555555872a0, nexeccalls=nexeccalls@entry=1) at lvm.c:441
#13 0x00005555555616e5 in luaD_call (L=0x5555555872a0, func=0x5555555876a0, nResults=<optimized out>) at ldo.c:378
#14 0x000055555556080b in luaD_rawrunprotected (L=L@entry=0x5555555872a0, f=f@entry=0x55555555b8d0 <f_call>, ud=ud@entry=0x7fffffffcfa0) at ldo.c:116
#15 0x0000555555561889 in luaD_pcall (L=L@entry=0x5555555872a0, func=func@entry=0x55555555b8d0 <f_call>, u=u@entry=0x7fffffffcfa0, old_top=64, ef=<optimized out>) at ldo.c:464
#16 0x000055555555ea58 in lua_pcall (L=L@entry=0x5555555872a0, nargs=nargs@entry=0, nresults=nresults@entry=0, errfunc=errfunc@entry=2) at lapi.c:821
#17 0x000055555555a8db in docall (L=L@entry=0x5555555872a0, narg=narg@entry=0, clear=clear@entry=1) at lua.c:102
#18 0x000055555555ad2f in dostring (L=L@entry=0x5555555872a0, s=0x7fffffffd820 "print(require(\"lgi\").Gtk.Window{}.child)", name=name@entry=0x55555557a083 "=(command line)") at lua.c:141
#19 0x000055555555b370 in runargs (n=3, argv=0x7fffffffd408, L=0x5555555872a0) at lua.c:304
#20 pmain (L=0x5555555872a0) at lua.c:359
#21 0x0000555555560fff in luaD_precall (L=L@entry=0x5555555872a0, func=<optimized out>, func@entry=0x555555587670, nresults=0) at ldo.c:320
#22 0x00005555555616b4 in luaD_call (L=0x5555555872a0, func=0x555555587670, nResults=<optimized out>) at ldo.c:377
#23 0x000055555556080b in luaD_rawrunprotected (L=L@entry=0x5555555872a0, f=f@entry=0x55555555b8e0 <f_Ccall>, ud=ud@entry=0x7fffffffd290) at ldo.c:116
#24 0x0000555555561889 in luaD_pcall (L=L@entry=0x5555555872a0, func=func@entry=0x55555555b8e0 <f_Ccall>, u=u@entry=0x7fffffffd290, old_top=16, ef=ef@entry=0) at ldo.c:464
#25 0x000055555555eae7 in lua_cpcall (L=L@entry=0x5555555872a0, func=func@entry=0x55555555b150 <pmain>, ud=ud@entry=0x7fffffffd2c0) at lapi.c:856
#26 0x000055555555a6ea in main (argc=3, argv=0x7fffffffd408) at lua.c:387

In frame 1, tag is GI_TYPE_TAG_INTERFACE yet arg->v_string clearly points to the string lua, so something is not alright here, but I have no idea what's wrong.

Using lgi 0.9.2, lua 5.1.5 (but the same happens with luajit) and gtk 2.24.33.

psychon commented 2 years ago

and gtk 2.24.33.

Uhm.... sorry, but... why? GTK 2 is end-of-life and GTK 2.24.33 is almost 1.5 years old.

I can't even find a GTK 2 package for Debian testing, so apparently Debian already got rid of this.

Could you try whether this problem also occurs with a current GTK version?

DirtYiCE commented 2 years ago

No, sorry, I don't have gtk3 installed, and I'd like to keep that abomination away from my system as long as possible. But I saw that there are gtk2 specific workarounds, so I thought it's still supported: https://github.com/lgi-devs/lgi/blob/60b66d3a283f277fece5cfdb507c7dc9a6309361/lgi/override/Gtk.lua#L634-L640

psychon commented 2 years ago

Wow, that code is nine years old: https://github.com/lgi-devs/lgi/commit/1a9d4931d52a1153ca33f03c809b94ed5ca7c24c

Also, I can't say that this is more or less supported than the rest of LGI. People use it. Sometimes they find problems. Sometimes they report them. Sometimes I can do something about the problems. Sometimes not.

But if I understand the code you found correctly, then... doesn't this try to make the child property inaccessible because it does not work? And the above commit says that this comes from #58 and the backtrace in that issue looks quite a lot like the one you found.

So... apparently either the code you found or the the code here does not work any more. After nine years. It certainly looks different. Back then, this code was on "the main level" and these days it is wrapped in a if Gtk.Container that comes from eeafbb5dd4a724811431e84edb4c259aa82b1961. Perhaps adding GTK4 support somehow broke GTK2?

Dunno, sorry.

DirtYiCE commented 2 years ago

Hmm, based on the comment I though it wanted to get rid of this: https://developer-old.gnome.org/gtk2/2.24/GtkBin.html#gtk-bin-get-child while still keeping the lgi's own child override, but the commit message says otherwise. It looks like gtk4 no longer has GtkContainer, that's why that if is required. I don't know how that workaround worked originally, but now in ilua:

> require('lgi').Gtk.Bin._field
{}
> getmetatable(require('lgi').Gtk.Bin._field)
{__index=function: 0x7fd87995d120}

so I don't think that = nil actually does anything.

psychon commented 2 years ago

If you want to invest more time into this:

You could try building the version with the above commit and see if it works. Then you could try a git bisect to figure out when it broke and check if that finds anything useful.

No idea if this would actually help. This is all before I even knew lgi existed, I think.