Anything like GDestroyNotify in the mm api?

Aleksander Morgado aleksander at aleksander.es
Mon Oct 5 07:51:08 UTC 2020


Hey Jessy,

>
> I am using MM in a C++ project, but my question won't be related to C++ besides a very high level description of what I did.
>
> To get MM functions to invoke bound C++ functions as callbacks, I had to generate a small structure for each MM function call that automatically destroys itself once the callback fires. This works perfectly (mostly)!
>
> Except! If the MM function is cancelled, my wrapping structure is never invoked, never freed, and I get a memory leak. My current solution is to use g_cancellable_connect to trigger the struct's destruction when I cancel the MM operation. That is when I saw that g_cancellable_connect accepts an optional GDestroyNotify* callback, and I started thinking about how much more flexible the libmm-glib API would be if functions that accepted a GCancellable, callback, and userdata ALSO supported a GDestroyNotify style callback for freeing userdata.
>
> I know I can't expect a massive API change to a mature project because it would be convenient to one guy who is working in a different language, but I wanted to bring the idea up in case anyone else likes the idea, or knows why it was not implemented.
>

>From the point of view of the user of libmm-glib APIs, you MUST assume
that if you provide a GCallback to *any* async method, the GCallback
will *always* be called for you. And always means always, when the
async operation finishes successfully, when it fails, or when it's
cancelled. This is a guarantee that the library gives you, and
therefore if it doesn't happen, it's a bug in the library. Therefore,
if you pass a GCallback with a user_data that you have allocated in
heap, you're responsible for calling whatever free method that
user_data requires once the GCallback has been called. If you're
getting a memory leak, it could mean you're not doing this. Also, if
you pass a GCallback, you should call the corresponding _finish()
method of the async operation. This is not strictly needed in all
cases, but I'd suggest to always call finish() unconditionally.

If you look at the above, you'll see why you don't really need a
GDestroyNotify in the async methods. Actually, none of the usual GIO
async methods will ask you to provide a GDestroyNotify, because the
guarantee that the callback is called always lets you run whatever
free() you need yourself in the callback itself.

The GDestroyNotify in g_cancellable_connect() is required so that you
can safely assume the user_data is freed whenever the handler is
disconnected (because you're really adding a signal handler) or the
cancellation has happened (as this is a single-time event). This logic
doesn't really apply to normal async methods like the ones we have in
libmm-glib.

So now, you say the GCallback is not being called if the operation is
cancelled. Could you send a short tester to show this issue? Does the
issue happen always with the same async method or with all that you've
tried?

-- 
Aleksander
https://aleksander.es


More information about the ModemManager-devel mailing list