Question

i'm working on porting this C API in go https://github.com/shammash/vde3, the library has is own event loop that use libevent, i'm using CGO.

the library require a full vde_event_handler that is composed this way

{event_add = 0x7fffe4de0db0, event_del = 0xc2000123a8, timeout_add = 0xc200000090, timeout_del = 0xc200010400}

a struct with a series of pointers to functions

during execution this field are set to NULL and i can't understand why, i think it may be the go garbage collector that (for some reason) find the reference dandling and remove them, but this shouldn't be the case

this is the incriminated function https://github.com/kurojishi/govde3/blob/master/govde.go#L23

func createNewEventHandler() *C.vde_event_handler {
    var libevent_eh C.vde_event_handler
    C.event_base_new()
    return &libevent_eh
}

and here is a gdb log

(gdb) p *libevenet_eh
No symbol "libevenet_eh" in current context.
(gdb) p *libevent_eh
$1 = {event_add = 0x7fffe0000900, event_del = 0x30302e3028, timeout_add = 0x65736c6166, timeout_del = 0x0}
(gdb) info locals
libevent_eh = 0xc200000098
err = {__methods = 0x0, __object = 0x0}
(gdb) n

Breakpoint 1, govde.createNewEventHandler ()
at /home/kurojishi/golang/src/github.com/kurojishi/govde3/govde.go:23
23  func createNewEventHandler() C.vde_event_handler {
(gdb) info locals
$ret11 = {event_add = 0x7fffe4de0db0, event_del = 0xc2000123a8, timeout_add = 0xc200000090, timeout_del = 0xc200010400}
(gdb) n

Breakpoint 2, govde.createNewEventHandler ()
at /home/kurojishi/golang/src/github.com/kurojishi/govde3/govde.go:24
24      var libevent_eh C.vde_event_handler
(gdb) info locals
libevent_eh = {event_add = 0x0, event_del = 0x3, timeout_add = 0x7fffe4de0f8f, timeout_del = 0x7fffe4de0f8f}
$ret11 = {event_add = 0x0, event_del = 0x0, timeout_add = 0x0, timeout_del = 0x0}
Was it helpful?

Solution

You are allocating a new event handler in Go in createNewEventHandler, passing it to the C code in VdeContext.Init, and then dropping the pointer. The effect is that sometime after VdeContext.Init returns, the Go garbage collector will collect the event handler structure, even though the C code still has a pointer to it. The code will be left holding a pointer to memory that will change unpredictably.

When you allocate memory in Go and pass a pointer to C, you must keep the pointer alive in Go for as long as the C code needs to reference it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top