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 _______________________________________________ ModemManager-devel mailing list ModemManager-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel