-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SEGFAULT using glib.Value #61
Comments
I think this issue can be ultimately retraced to https://pkg.go.dev/unsafe#Pointer , especially the casting of The docs state that, although the casting is safe to to under certain circumstances, saving the value of the We do have a couple instances of code like this in the bindings: https://github.com/go-gst/go-gst/blob/46f74cb97a436a19871ba0e65f63c7a219e992c1/gst/pbutils/discoverer.go#L70C1-L73 (even the original gotk3 does some casts like this) The ultimate reason for using the unsafe package in the bindings is to escape the type checks, although the correct pointer type for this is This can only be fixed by breaking a lot of the current glib API. I can also only test very small parts of the resulting code, since I'm nowhere near using every little bit of the features in my code. The reason this is a big change, is that currently all type marshalers use go-gst/gst/pbutils/discoverer.go Lines 16 to 64 in 46f74cb
I will try to remove all instances of |
may also relate to #60 |
as mentioned in #51 the reason |
I still get Segfaults when I use @tinyzimmer @danjenkins could you try to run one of your gstreamer applications with |
the above reproduction is not complete, it doesn't crash every time. if a GC is forced during the //export goObjectSetProperty
func goObjectSetProperty(obj *C.GObject, propID C.guint, val *C.GValue, param *C.GParamSpec) {
defer func() {
if r := recover(); r != nil {
fmt.Println("recovered")
panic(r)
}
}()
runtime.GC() // forcing a GC here crashes with SIGSEGV
WithPointerTransferOriginal(unsafe.Pointer(obj), func(object *Object, subclass GoObjectSubclass) {
iface := subclass.(interface{ SetProperty(*Object, uint, *Value) })
iface.SetProperty(object, uint(propID-1), ValueFromNative(unsafe.Pointer(val)))
})
} I'll look deeper into it. Help appreciated. |
I pinned the Issue down to the finalizer on the This only happens because I am registering and using a custom element in the same application. func ValueInit(t Type) (*Value, error) {
c := C._g_value_init(C.GType(t))
if c == nil {
return nil, nilPtrErr
}
v := &Value{c}
// runtime.SetFinalizer(v, (*Value).unset) <- uncommenting this crashes if the GC intervenes
return v, nil
} The steps that are happening are:
@sdroege could you provide some information regarding the internals of |
It looks like a simple |
Sorry I've not replied to these @RSWilli - was pretty much unavailable last week due to illness. Well done on figuring it out - looks like a pain to track down. |
@danjenkins yeah it was. Now after finding the fix I think this may also be a problem in other parts of the bindings. Essentially, when we do not keep the value alive, the finalizer can run before the C call is done and free the C value. This can happen with all intermediate values that wrap some C object, where a user does not have a reference to. |
That would make sense. But at the same time if this was a problem elsewhere I'd expect to have hit a problem by now? |
That depends entirely on your setup and your use case. The GC runs in parallel so it always was a race condition. If your GC never decides to eagerly clean up the heap, then you will never run into this issue. I run my prod environment with I also frequently update the gstreamer pipeline (so I call |
@danjenkins as said above, you can more easily detect these rare errors when you run your app with the following two env vars set:
Combined this effectively means that your application will not have any uncollected garbage memory lying around. These two settings dramatically increase the CPU consumption of the GC, so they are not recommended for production in this combination |
Whilst thinking about more cases where this issue could pop up, the following came into mind: https://github.com/go-gst/go-gst/blob/main/gst/gst_element_factory.go#L40-L76 The temporary GValues could be cleaned up during usage in CGO, so they should be kept alive. I'm going to add a |
When setting a property on a custom bin I sometimes get a
SIGSEGV
.The error in the stack trace is reported to be at https://github.com/go-gst/go-glib/blob/main/glib/gvalue.go#L52 in the called C function in https://github.com/go-gst/go-glib/blob/b2d34240bcb44a1b341b2f094eb2ab33e1a2aa98/glib/glib.go.h#L126-L128
I will investigate and provide further details.
Currently I suspect that the reason is the conversion from C to golang, and if timed correctly it may interfere with some GC magic.
The text was updated successfully, but these errors were encountered: