jwharm / java-gi

GObject-Introspection bindings generator for Java
GNU Lesser General Public License v2.1
93 stars 9 forks source link

Fatal Error : C [libgio-2.0.so.0+0xcb1b5] g_list_model_get_n_items+0x25 #113

Closed SudoDios closed 4 months ago

SudoDios commented 4 months ago

Hi. I get this error : C [libgio-2.0.so.0+0xcb1b5] g_list_model_get_n_items+0x25 when create a columnview with SelectionModel (single,multi). how fix it ?

jwharm commented 4 months ago

Please add the source code.

SudoDios commented 4 months ago

ok i will

SudoDios commented 4 months ago
fun main (args : Array<String>) {
    val app = Application("co.ex.test", ApplicationFlags.DEFAULT_FLAGS)
    app.onActivate {
        val window = ApplicationWindow(app).apply {
            val scrolledWindow = ScrolledWindow().apply {
                halign = Align.FILL
                hexpand = true
            }
            val columnGen = makeColumn()

            makeList().sortedBy { it.name }.forEach {
                columnGen.first.append(it)
            }
            scrolledWindow.child = columnGen.second
            child = scrolledWindow
        }
        window.present()
    }
    app.run(args)
}

private fun makeColumn () : Pair<ListStore, ColumnView>{

    val nameFac = SignalListItemFactory().apply {
        onSetup { obj ->
            val row = obj as ColumnViewCell
            row.child = Box(Orientation.HORIZONTAL,0).apply {
                marginEnd = 8
                marginBottom = 8
                marginStart = 8
                marginTop = 8
                halign = Align.FILL
                hexpand = true

                val icon = Image.fromIconName("folder")

                val label = Label("").apply {
                    marginStart = 12

                    halign = Align.START
                    hexpand = true
                }

                append(icon)
                append(label)
            }
        }
        onBind { obj ->
            val row = obj as ColumnViewCell
            val child = row.child as Box
            val label = child.lastChild as Label
            val model = obj.item as FileModel
            label.label = model.name
        }
    }
    val sizeFac = SignalListItemFactory().apply {
        onSetup { obj ->
            val row = obj as ColumnViewCell
            row.child = Label("").apply {
                marginEnd = 8
                marginBottom = 8
                marginStart = 8
                marginTop = 8
                halign = Align.START
                hexpand = true
            }
        }
        onBind { obj ->
            val row = obj as ColumnViewCell
            val child = row.child as Label
            val model = obj.item as FileModel
            child.label = model.size.formatToSizeFile()
        }
    }

    val store = ListStore(FileModel.gType)

    val columnView = ColumnView(MultiSelection(store)).apply {
        halign = Align.FILL
        hexpand = true
    }

    val nameColumn = ColumnViewColumn("Name",nameFac).apply {
        expand = true
    }
    val sizeColumn = ColumnViewColumn("Size",sizeFac).apply {
        fixedWidth = -1
    }
    columnView.appendColumn(nameColumn)
    columnView.appendColumn(sizeColumn)

    return Pair(store,columnView)
}

private fun makeList () : List<FileModel> {
    val file = File("/your/home/dir")
    val out = mutableListOf<FileModel>()
    file.listFiles()?.forEach {
        out.add(FileModel.create().apply {
            name = it.name
            size = it.length()
            path = it.absolutePath
            modified = it.lastModified()
        })
    }
    return out
}

class FileModel(address: MemorySegment?) : GObject(address) {
    companion object {
        var gType: Type = Types.register<FileModel, ObjectClass>(FileModel::class.java)
        fun create(): FileModel {
            return newInstance(gType)
        }
    }
    var name : String = ""
    var path : String = ""
    var size : Long = 0
    var modified : Long = 0

}

This is an example of my code. To see the problem, select an item in list and move in the list with the up and down arrow keys on keyboard. After a few moments you will see the error

jwharm commented 4 months ago

I can't reproduce the error, but I've seen a similar error before. I'm 99% sure it's related to garbage collection of the ListStore.

Looking at the main function and the app.onActivate callback, you see that the ListStore is constructed (as a part of the columnGen Pair) and then the window is presented. Past that point, the ListStore instance is not used anymore in the kotlin code. It's still used by native code, but the JVM is not aware of that. So when after a while the Garbage Collector runs, it destroys the ListStore instance.

If you put the ListStore (or in your case, the columnGen variable) in a public field, the JVM should keep it alive, and the crash should disappear.

SudoDios commented 4 months ago

If you put the ListStore (or in your case, the columnGen variable) in a public field, the JVM should keep it alive, and the crash should disappear.

I will test this

SudoDios commented 4 months ago

@jwharm Yes, it was done!
The problem was the JVM garbage collector. thank you 👍.

jwharm commented 4 months ago

@SudoDios This turned out to be a bug in java-gi after all. It will be fixed in the next release.

SudoDios commented 4 months ago

@jwharm Really?!
How interesting.