kuzudb / go-kuzu

Go language binding for Kùzu graph database management system
http://kuzudb.com
MIT License
5 stars 0 forks source link

Panic in the C code when doing performance benchmarks #21

Open omer9564 opened 15 hours ago

omer9564 commented 15 hours ago

I'm getting a panic in when running "stress" on the kuzudb using the go-kuzu package.

The code I'm using to do this is ( I also tried building the queries myself instead of using the query builder, it didn't help ): Worth pointing out - increasing the sleepMiliseconds does make this happen less frequently. Also tried saving the results in some slice as I saw in the panic something related to the GC which didn't help

package main

import (
    "fmt"
    cypher "github.com/eighthGnom/scypher"
    "github.com/kuzudb/go-kuzu"
    "github.com/samber/lo"
    "log"
    "os"
    "time"
)

const dbPath = "/tmp/kuzudb3"

const sleepMiliseconds = 0

var numUsers = 10_000
var numInstancesPerDepth = 10
var depthCount = 5

func exec(conn *kuzu.Connection, query string) kuzu.QueryResult {
    r, err := conn.Query(query)
    if err != nil {
        panic(err)
    }
    time.Sleep(time.Millisecond * sleepMiliseconds)
    return r
}

func initDB() *kuzu.Connection {
    os.RemoveAll(dbPath)
    sysConfig := kuzu.DefaultSystemConfig()
    sysConfig.BufferPoolSize = 1024 * 1024 * 1024
    db, err := kuzu.OpenDatabase(dbPath, sysConfig)
    if err != nil {
        log.Fatal(err)
    }
    conn, err := kuzu.OpenConnection(db)
    if err != nil {
        log.Fatal(err)
    }
    schemaMigrations := []string{
        "CREATE NODE TABLE IF NOT EXISTS User(id STRING,first_name STRING, PRIMARY KEY (id))",
        "CREATE NODE TABLE IF NOT EXISTS Folder(id STRING, PRIMARY KEY (id))",
        "CREATE REL TABLE IF NOT EXISTS RoleAssignment(FROM User TO Folder, role STRING)",
        "CREATE REL TABLE IF NOT EXISTS Relationship(FROM Folder TO Folder, relation STRING)",
    }
    for _, query := range schemaMigrations {
        r := exec(&conn, query)
        r.Close()
    }
    return &conn
}

func populateUser(conn *kuzu.Connection, userI int, user string) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered call to div", r)
        }
    }()
    userInsert, err := cypher.NewQueryBuilder().Create(
        cypher.NewNode().SetLabel("User").SetProps(
            cypher.Property{
                Key:   "id",
                Value: user,
            },
            cypher.Property{
                Key:   "first_name",
                Value: fmt.Sprintf("user %d", userI),
            },
        ).AsPattern()).Build()
    if err != nil {
        panic(err)
    }
    fmt.Println(userInsert)
    exec(conn, userInsert)
    for depth := 0; depth < depthCount; depth++ {
        for instanceI := 0; instanceI < numInstancesPerDepth; instanceI++ {
            queriesToExecute := make([]string, 0)
            instanceDepth, err := cypher.NewQueryBuilder().Merge(
                cypher.NewNode().SetLabel("Folder").SetProps(
                    cypher.Property{
                        Key:   "id",
                        Value: fmt.Sprintf("instance-%d-%d", depth, instanceI),
                    },
                ).AsPattern()).Build()
            if err != nil {
                panic(err)
            }
            queriesToExecute = append(queriesToExecute, instanceDepth)
            if depth > 0 {
                parents := []string{fmt.Sprintf("instance-%d-%d", depth-1, instanceI)}
                if instanceI%2 == 0 && instanceI > 0 {
                    parents = append(parents, fmt.Sprintf("instance-%d-%d", depth-1, instanceI-1))
                } else if instanceI%2 == 1 && instanceI > 0 {
                    parents = append(parents, fmt.Sprintf("instance-%d-%d", depth, instanceI-1))
                }

                i1, err := cypher.NewNode().SetLabel("Folder").SetVariable("i1").ToCypher()
                if err != nil {
                    panic(err)
                }
                i2, err := cypher.NewNode().SetLabel("Folder").SetVariable("i2").ToCypher()
                if err != nil {
                    panic(err)
                }
                relationships, err := cypher.NewQueryBuilder().
                    AddRaw("MATCH "+i1+", "+i2).
                    Where(
                        cypher.NewConditionBuilder().
                            AddCondition(
                                cypher.ConditionalConfig{
                                    Variable: "i1",
                                    Field:    "id",
                                    Operator: cypher.IN,
                                    Check:    parents,
                                },
                            ).
                            And().
                            AddCondition(
                                cypher.ConditionalConfig{
                                    Variable: "i2",
                                    Field:    "id",
                                    Operator: cypher.EqualTo,
                                    Check:    fmt.Sprintf("instance-%d-%d", depth, instanceI),
                                },
                            ).ReleaseConditions()...,
                    ).
                    Merge(
                        cypher.NewNode().SetVariable("i1").AsPattern(),
                        cypher.NewEdge().SetLabel("Relationship").
                            SetProps(cypher.Property{Key: "relation", Value: "parent"}).AsPattern(),
                        cypher.NewNode().SetVariable("i2").AsPattern(),
                    ).Build()
                if err != nil {
                    panic(err)
                }
                queriesToExecute = append(queriesToExecute, relationships)
            } else {
                u1, err := cypher.NewNode().SetLabel("User").SetVariable("u1").ToCypher()
                if err != nil {
                    panic(err)
                }
                i1, err := cypher.NewNode().SetLabel("Folder").SetVariable("i1").ToCypher()
                if err != nil {
                    panic(err)
                }
                relationships, err := cypher.NewQueryBuilder().
                    AddRaw("MATCH "+u1+", "+i1).
                    Where(
                        cypher.NewConditionBuilder().
                            AddCondition(
                                cypher.ConditionalConfig{
                                    Variable: "u1",
                                    Field:    "id",
                                    Operator: cypher.EqualTo,
                                    Check:    user,
                                },
                            ).
                            And().
                            AddCondition(
                                cypher.ConditionalConfig{
                                    Variable: "i1",
                                    Field:    "id",
                                    Operator: cypher.EqualTo,
                                    Check:    fmt.Sprintf("instance-%d-%d", depth, instanceI),
                                },
                            ).ReleaseConditions()...,
                    ).
                    Merge(
                        cypher.NewNode().SetVariable("u1").AsPattern(),
                        cypher.NewEdge().SetLabel("RoleAssignment").
                            SetProps(cypher.Property{Key: "role", Value: "Admin"}).AsPattern(),
                        cypher.NewNode().SetVariable("i1").AsPattern(),
                    ).Build()
                if err != nil {
                    panic(err)
                }
                queriesToExecute = append(queriesToExecute, relationships)
            }

            lo.ForEach(queriesToExecute, func(query string, _ int) {
                fmt.Println("Executing:\n", query)
                exec(conn, query)
            })
        }
    }
}

func transaction(conn *kuzu.Connection, userI int, userStr string, f func(conn *kuzu.Connection, userI int, user string)) {
    _, err := conn.Query("BEGIN TRANSACTION")
    if err != nil {
        panic(err)
    }
    f(conn, userI, userStr)
    defer func() {
        finalizer := "COMMIT"
        if err != nil {
            finalizer = "ROLLBACK"
        }
        fmt.Println("Performing ", finalizer)
        _, err := conn.Query(finalizer)
        if err != nil {
            panic(err)
        }
    }()
}

func populateDB(conn *kuzu.Connection) {
    for userI := 0; userI < numUsers; userI++ {
        transaction(conn, userI, fmt.Sprintf("user-%d", userI), populateUser)
    }
}

func main() {
    conn := initDB()
    populateDB(conn)
    fmt.Println("finished")
    defer conn.Close()
}
SIGSEGV: segmentation violation
PC=0x102f0ff88 m=0 sigcode=2 addr=0x48
signal arrived during cgo execution

goroutine 1 gp=0x140000021c0 m=0 mp=0x1008edb20 [syscall]:
runtime.cgocall(0x1007af258, 0x140001d8f98)
        /usr/local/go/src/runtime/cgocall.go:157 +0x44 fp=0x140001d8f60 sp=0x140001d8f20 pc=0x1006c5014
github.com/kuzudb/go-kuzu._Cfunc_kuzu_connection_query(0x140001941d0, 0x600003065b60, 0x14000444030)
        _cgo_gotypes.go:463 +0x34 fp=0x140001d8f90 sp=0x140001d8f60 pc=0x100786944
github.com/kuzudb/go-kuzu.(*Connection).Query.func3(0x140001941d0, 0x600003065b60, 0x14000444030)
        /Users/myuser/go/pkg/mod/github.com/kuzudb/go-kuzu@v0.6.0/connection.go:77 +0x88 fp=0x140001d8fc0 sp=0x140001d8f90 pc=0x1007873b8
github.com/kuzudb/go-kuzu.(*Connection).Query(0x140001941d0, {0x1400042fe90?, 0x31?})
        /Users/myuser/go/pkg/mod/github.com/kuzudb/go-kuzu@v0.6.0/connection.go:77 +0xb8 fp=0x140001d9050 sp=0x140001d8fc0 pc=0x1007870a8
main.exec(0x14000594000?, {0x1400042fe90?, 0x140000021c0?})
        /private/tmp/kuzu-panic/main.go:23 +0x3c fp=0x140001d9110 sp=0x140001d9050 pc=0x1007ac9bc
main.populateUser.func2({0x1400042fe90, 0x24}, 0x1007b29f5?)
        /private/tmp/kuzu-panic/main.go:185 +0x90 fp=0x140001d91d0 sp=0x140001d9110 pc=0x1007aeb50
github.com/samber/lo.ForEach[...](...)
        /Users/myuser/go/pkg/mod/github.com/samber/lo@v1.47.0/slice.go:93
main.populateUser(0x140001941d0, 0xf, {0x1400040d8f4, 0x7})
        /private/tmp/kuzu-panic/main.go:183 +0x1ab8 fp=0x140001d9de0 sp=0x140001d91d0 pc=0x1007ae778
main.transaction(0x140001941d0, 0xf, {0x1400040d8f4, 0x7}, 0x100813b40)
        /private/tmp/kuzu-panic/main.go:196 +0x70 fp=0x140001d9e80 sp=0x140001d9de0 pc=0x1007aecc0
main.populateDB(0x140001941d0)
        /private/tmp/kuzu-panic/main.go:212 +0x7c fp=0x140001d9ed0 sp=0x140001d9e80 pc=0x1007aeedc
main.main()
        /private/tmp/kuzu-panic/main.go:218 +0x2c fp=0x140001d9f40 sp=0x140001d9ed0 pc=0x1007aef4c
runtime.main()
        /usr/local/go/src/runtime/proc.go:271 +0x28c fp=0x140001d9fd0 sp=0x140001d9f40 pc=0x1006f92cc
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140001d9fd0 sp=0x140001d9fd0 pc=0x10072a094

goroutine 2 gp=0x14000002c40 m=nil [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000054f90 sp=0x14000054f70 pc=0x1006f96f8
runtime.goparkunlock(...)
        /usr/local/go/src/runtime/proc.go:408
runtime.forcegchelper()
        /usr/local/go/src/runtime/proc.go:326 +0xb8 fp=0x14000054fd0 sp=0x14000054f90 pc=0x1006f9588
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x14000054fd0 sp=0x14000054fd0 pc=0x10072a094
created by runtime.init.6 in goroutine 1
        /usr/local/go/src/runtime/proc.go:314 +0x24

goroutine 3 gp=0x14000003180 m=nil [runnable]:
runtime.goschedIfBusy()
        /usr/local/go/src/runtime/proc.go:365 +0x34 fp=0x14000055760 sp=0x14000055740 pc=0x1006f9614
runtime.bgsweep(0x14000080000)
        /usr/local/go/src/runtime/mgcsweep.go:302 +0x178 fp=0x140000557b0 sp=0x14000055760 pc=0x1006e6238
runtime.gcenable.gowrap1()
        /usr/local/go/src/runtime/mgc.go:203 +0x28 fp=0x140000557d0 sp=0x140000557b0 pc=0x1006da5d8
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000557d0 sp=0x140000557d0 pc=0x10072a094
created by runtime.gcenable in goroutine 1
        /usr/local/go/src/runtime/mgc.go:203 +0x6c

goroutine 18 gp=0x14000104380 m=nil [GC scavenge wait]:
runtime.gopark(0x10000?, 0x1007e12d0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000050760 sp=0x14000050740 pc=0x1006f96f8
runtime.goparkunlock(...)
        /usr/local/go/src/runtime/proc.go:408
runtime.(*scavengerState).park(0x1008ed440)
        /usr/local/go/src/runtime/mgcscavenge.go:425 +0x5c fp=0x14000050790 sp=0x14000050760 pc=0x1006e3b4c
runtime.bgscavenge(0x14000080000)
        /usr/local/go/src/runtime/mgcscavenge.go:658 +0xac fp=0x140000507b0 sp=0x14000050790 pc=0x1006e410c
runtime.gcenable.gowrap2()
        /usr/local/go/src/runtime/mgc.go:204 +0x28 fp=0x140000507d0 sp=0x140000507b0 pc=0x1006da578
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000507d0 sp=0x140000507d0 pc=0x10072a094
created by runtime.gcenable in goroutine 1
        /usr/local/go/src/runtime/mgc.go:204 +0xac

goroutine 34 gp=0x14000188380 m=8 mp=0x14000500008 [syscall]:
runtime.cgocall(0x1007af964, 0x140000544f8)
        /usr/local/go/src/runtime/cgocall.go:157 +0x44 fp=0x140000544c0 sp=0x14000054480 pc=0x1006c5014
github.com/kuzudb/go-kuzu._Cfunc_kuzu_database_destroy(0x140001941c0)
        _cgo_gotypes.go:546 +0x30 fp=0x140000544f0 sp=0x140000544c0 pc=0x1007869d0
github.com/kuzudb/go-kuzu.(*Database).Close.func1(0x140001941c0)
        /Users/myuser/go/pkg/mod/github.com/kuzudb/go-kuzu@v0.6.0/database.go:90 +0x4c fp=0x14000054520 sp=0x140000544f0 pc=0x10078796c
github.com/kuzudb/go-kuzu.(*Database).Close(0x140001941c0)
        /Users/myuser/go/pkg/mod/github.com/kuzudb/go-kuzu@v0.6.0/database.go:90 +0x34 fp=0x14000054540 sp=0x14000054520 pc=0x1007878f4
github.com/kuzudb/go-kuzu.OpenDatabase.func1(0x0?)
        /Users/myuser/go/pkg/mod/github.com/kuzudb/go-kuzu@v0.6.0/database.go:67 +0x1c fp=0x14000054560 sp=0x14000054540 pc=0x100787a7c
runtime.call16(0x0, 0x100813ba0, 0x1400043a000, 0x10, 0x10, 0x10, 0x14000054600)
        /usr/local/go/src/runtime/asm_arm64.s:503 +0x78 fp=0x14000054580 sp=0x14000054560 pc=0x100728098
runtime.runfinq()
        /usr/local/go/src/runtime/mfinal.go:256 +0x3e8 fp=0x140000547d0 sp=0x14000054580 pc=0x1006d9988
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000547d0 sp=0x140000547d0 pc=0x10072a094
created by runtime.createfing in goroutine 1
        /usr/local/go/src/runtime/mfinal.go:164 +0x80

goroutine 4 gp=0x140000036c0 m=nil [GC worker (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000055f30 sp=0x14000055f10 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x14000055fd0 sp=0x14000055f30 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x14000055fd0 sp=0x14000055fd0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 5 gp=0x14000003880 m=nil [GC worker (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000056730 sp=0x14000056710 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140000567d0 sp=0x14000056730 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000567d0 sp=0x140000567d0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 19 gp=0x14000104540 m=nil [GC worker (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000050f30 sp=0x14000050f10 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x14000050fd0 sp=0x14000050f30 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x14000050fd0 sp=0x14000050fd0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 20 gp=0x14000104700 m=nil [GC worker (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000051730 sp=0x14000051710 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140000517d0 sp=0x14000051730 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000517d0 sp=0x140000517d0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 6 gp=0x14000003a40 m=nil [GC worker (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000056f30 sp=0x14000056f10 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x14000056fd0 sp=0x14000056f30 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x14000056fd0 sp=0x14000056fd0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 7 gp=0x14000003c00 m=nil [GC worker (idle)]:
runtime.gopark(0x2c507e9bcb732?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000057730 sp=0x14000057710 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140000577d0 sp=0x14000057730 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000577d0 sp=0x140000577d0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 8 gp=0x14000003dc0 m=nil [GC worker (idle)]:
runtime.gopark(0x2c507e9bd229e?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000057f30 sp=0x14000057f10 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x14000057fd0 sp=0x14000057f30 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x14000057fd0 sp=0x14000057fd0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 21 gp=0x140001048c0 m=nil [GC worker (idle)]:
runtime.gopark(0x2c507e9bc4f31?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000051f30 sp=0x14000051f10 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x14000051fd0 sp=0x14000051f30 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x14000051fd0 sp=0x14000051fd0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 35 gp=0x14000188540 m=nil [GC worker (idle)]:
runtime.gopark(0x100953680?, 0x1?, 0xa2?, 0xd3?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000484730 sp=0x14000484710 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140004847d0 sp=0x14000484730 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140004847d0 sp=0x140004847d0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 22 gp=0x14000104a80 m=nil [GC worker (idle)]:
runtime.gopark(0x100953680?, 0x1?, 0xdb?, 0x1?, 0x0?)
        /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x14000052730 sp=0x14000052710 pc=0x1006f96f8
runtime.gcBgMarkWorker()
        /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140000527d0 sp=0x14000052730 pc=0x1006dc468
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000527d0 sp=0x140000527d0 pc=0x10072a094
created by runtime.gcBgMarkStartWorkers in goroutine 1
        /usr/local/go/src/runtime/mgc.go:1234 +0x28

r0      0x0
r1      0x600001bde6a0
r2      0x102f56058
r3      0x8
r4      0x3
r5      0x1440
r6      0x600000cdd440
r7      0x18a932428
r8      0x0
r9      0x600001d43de0
r10     0x1
r11     0x1
r12     0x600003c5f730
r13     0x1ff800
r14     0x7fb
r15     0xbec1d025
r16     0x18a938c9c
r17     0x1e9b18198
r18     0x0
r19     0x16f741f28
r20     0x12b715f20
r21     0x600003c6d2b0
r22     0x0
r23     0x0
r24     0x16f742180
r25     0x16f741f18
r26     0x16f741ee8
r27     0x600000cdd440
r28     0x0
r29     0x16f741ea0
lr      0x102f0ff60
sp      0x16f741c10
pc      0x102f0ff88
fault   0x48

Process finished with the exit code 2
mewim commented 8 hours ago

Hi @omer9564,

I realized that there are some bugs in managing the life cycle of Go structs and the underlying C pointer. We need to make sure that the QueryResult and PreparedStatement structs are closed first, then the Connection can be closed, and finally Database can be closed, but the callback function we defined in runtime.SetFinalizer does not make such guarantee. I have fixed it in #22 by keeping reference pointers to ensure GC order and returning by pointer in all cases to avoid unexpected GC actions on copied structs. After this fix, I ran your script and it did not crash for > 30 minutes (it has not terminated yet, but I suppose the GC issue has been fixed). Since I realized it is not possible to re-release the Go package, and we need to make sure that all API binding have the same version as the main project, I am not releasing a new stable version for now, but you should be able to test the fix by go get github.com/kuzudb/go-kuzu@master.

omer9564 commented 8 hours ago

Hey @mewim , Thanks for the quick response. I will check it out later on this week.

mewim commented 8 hours ago

Hi @omer9564,

I am not concerning the API change. However, in general, as a principle of kuzu project, we make the versions of the database core, CLI, and all the API bindings consistent, so if we release v0.6.1, we need to release it for all the components. I will coordinate with the team to see if there are any additional fixes and changes in other client APIs need to come in before making a release.

omer9564 commented 8 hours ago

Yes I noticed it after re-reading your comment again so I went ahead and deleted this part from my comment 😅 Anyway because golang "releases" are based on git tags, I think deleting and recreating the tag on the latest commit might do what you aim for ( which is fixing the 0.6.0 tag in the golang project alone ) but not sure if this is also a nice solution