Skip to content

Race condition between Go's GC finalizer and active query result iteration #7

@jkumz

Description

@jkumz

There is a race condition between Go’s Garbage Collector and Cgo execution. The library currently suffers from intermittent SIGSEGV crashes (as seen in the stack trace) because Go finalizers are being triggered for Parent objects while Child objects are still accessing their memory via Cgo.

The trace shows Goroutine 35 (Go's internal Finalizer goroutine) calling lbug_query_result_destroy while Goroutine 133 is simultaneously executing lbug_flat_tuple_get_value. This results in a Use-After-Free crash because the QueryResult's memory buffer was freed by the finalizer while the FlatTuple was still reading from it

Trunacted stack trace:

goroutine 35 gp=0x14000180540 m=8 [syscall]:
runtime.cgocall(0x10537c1b8, 0x1400006e518)
github.com/LadybugDB/go-ladybug._Cfunc_lbug_query_result_destroy(0x14000825540)
github.com/LadybugDB/go-ladybug.(*QueryResult).Close.func1(...)
        /go-ladybug@v0.13.1/query_result.go:39

goroutine 133 gp=0x14000181880 m=nil [runnable]:
github.com/LadybugDB/go-ladybug.lbugValueToGoValue({0x152a23d38, ...})
        /go-ladybug@v0.13.1/value_helper.go:261
github.com/LadybugDB/go-ladybug.(*FlatTuple).GetValue(0x14000c10200, 0x1)
        /go-ladybug@v0.13.1/flat_tuple.go:77

Go's GC marks a QueryResult as unreachable as soon as the Go code no longer references it—even if a FlatTuple derived from it is still inside a C function. Go is unaware that the C-level FlatTuple depends on the QueryResult's memory.

Currently, finalizers are registered before checking the C return status (e.g., in QueryResult.Next() or OpenConnection()). If the C call fails the GC eventually collects this failed object calling the destroy function on a null or uninitialised handle and crashing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions