oboe
oboe copied to clipboard
How safely delete the error callback?
I am trying to write safe rust bindings for oboe, but I found the following situation.
For asynchronous error handling, ones must pass a pointer to a AudioStreamErrorCallback to AudioStreamBuilder::setErrorCallback, which is later passed to the AudioStream. In this scenario, the caller holds ownership of the callback (to allow sharing the error callback between multiple Streams, I suppose), and so it must delete it.
But I cannot find a safe way of doing it.
When a AudioStream receives an error, the error handler spawns a new thread that holds a reference to the AudioStream using a shared_ptr, and from that stream gets a raw pointer to the ErrorCallback (as seem here). But in the meantime, the main thread could have started closing and deleting the stream and callback.
The shared_ptr solves the problem of deleting the AudioStream from another thread (as discussed in #820 and #821), but I cannot find a way to guarantee that the ErrorCallback is not being used by the error callback thread when I try to delete it in the main thread.
I have thought of:
- holding a lock inside the error callback method, but by that point the error thread has already dereferenced the callbacks' method.
- try only deleting the callback at the end of
onErrorAfterClose, but an error may never happen, and the callback would leak.
The only safe way that I find of handling this situation is to leak the callback, but this is not ideal.
We hear your concerns and are discussing potential solutions. See #1603. We are considering a method to pass a shared_ptr in AudioStreamBuilder.setErrorCallback.
We added an API change that makes it easier to safely delete an error callback by using a shared_ptr. See #1626
We will document this technique and then can close this issue.
Documented now.