Anything like GDestroyNotify in the mm api?
jessy.diamondman at gmail.com
Mon Oct 5 09:00:49 UTC 2020
Thanks again for the reply.
I am aware that with a series of async calls that 'cancellation' as an idea
is questionable. What does it even mean?, etc...
Part of my confusion was running the following (to test cancellation) and
the bearer was still created.
This code was executed in a scheduled task run by the glib event loop, and
all of the code ran in the same iteration of the event loop. I expected
that the bearer creation logic would start in the next event loop
iteration, but now I see that the mm_modem_create_bearer call immediately
instructs MM to start creating the bearer, so by the time the next line of
my code is executed, it is too late to stop the creation. This is fine, and
I can deal with an extra bearer that I have to clean up later.
The real issue that is leading me through all of these tests is improving
my understanding of lifecycles when working with async MM functions. I want
to make sure that there is no possible scenario where I destroy one of my
C++ objects that tracks a MMModem, in the destructor I cancel and unref the
cancellable, the object is deleted, and then a callback comes through with
the user_data set to my freed object and I get a use after free. But it is
likely that this will just require me doing some more reading and
experimentation. If you know any good practices to prevent these kinds of
use after free issues, I would greatly appreciate any links or suggestions.
(And thanks for not minding me changing the topic).
Jessy Diamond Exum
On Mon, Oct 5, 2020 at 1:20 AM Aleksander Morgado <aleksander at aleksander.es>
> > Now I just need to understand why even when I call
> mm_modem_create_bearer and immediately cancel the GCancellable, My callback
> is called with the error "Operation was cancelled", but the bearer is still
> created. This is an unrelated issue, so I can create a new email thread on
> this question if I can't figure it out.
> That's easy to explain I think.
> Internally, all the async operations are implemented using GTasks.
> When the async operation starts, the GTask is created with the input
> GCancellable associated, and (by default) that means that if the
> cancellable is ever cancelled, the GTask is ALWAYS going to return a
> G_IO_ERROR_CANCELLED, even if the actual async operation may have
> finished successfully. So it may happen that the internal async method
> finished with a g_task_return_boolean(TRUE) or similar, but the actual
> g_task_propagate_boolean() called in the _finish() ends up returning a
> cancelled error instead of TRUE, because the GCancellable was
> cancelled meanwhile. See the docs for g_task_set_check_cancellable()
> which is the method that could be used to disable the default
> Now, another thing is the rationale of when this logic should be
> applied, or if it even makes sense to do that in certain operations
> like mm_modem_create_bearer(). You could argue that if this method
> fails with whatever reason, it must mean that the bearer object wasn't
> created, and I could probably agree with you. There would be two ways
> to solve this: make sure that internally the async method handles the
> cancellation gracefully and so we make sure the bearer is destroyed if
> it was created but the operation was cancelled; or otherwise make the
> operation not cancellable at all (ignoring the input cancellable).
> This is some thinking that we should put in all APIs I'm afraid; I'm
> sure there are some that already can be considered safe, but lots of
> others that change state or create objects probably aren't.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the ModemManager-devel