summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2017-10-05 23:29:13 +0200
committerAleksander Morgado <aleksander@aleksander.es>2017-10-05 23:59:26 +0200
commit3c3c9aa10f5921193cede586eeba9ba9591bdd76 (patch)
treed52a79d9e5277fdc4325c6eb2b0e6d80e83301f3
parent574ba880e5050e91ae1a67795f7240d384582a74 (diff)
downloadModemManager-3c3c9aa10f5921193cede586eeba9ba9591bdd76.tar.gz
plugin-manager: ensure valid reference during cancellation
Cancelling the port_context->cancellable may end up finishing the async task and completing the last reference of the port context. Avoid that by making sure we hold a valid reference for as long as we may need it. ==2277== Invalid read of size 4 ==2277== at 0x14ACE2: port_context_cancel (mm-plugin-manager.c:547) ==2277== by 0x14C32E: device_context_port_released (mm-plugin-manager.c:1142) ==2277== by 0x83831C7: ffi_call_unix64 (in /usr/lib/libffi.so.6.0.4) ==2277== by 0x8382C29: ffi_call (in /usr/lib/libffi.so.6.0.4) ==2277== by 0x64506A8: g_cclosure_marshal_generic (in /usr/lib/libgobject-2.0.so.0.5200.3) ==2277== by 0x644FEAC: g_closure_invoke (in /usr/lib/libgobject-2.0.so.0.5200.3) ==2277== by 0x64624AD: ??? (in /usr/lib/libgobject-2.0.so.0.5200.3) ==2277== by 0x646AC84: g_signal_emit_valist (in /usr/lib/libgobject-2.0.so.0.5200.3) ==2277== by 0x646B69E: g_signal_emit (in /usr/lib/libgobject-2.0.so.0.5200.3) ==2277== by 0x1483E7: mm_device_release_port (mm-device.c:196) ==2277== by 0x145D5D: device_removed (mm-base-manager.c:217) ==2277== by 0x1464A9: handle_kernel_event (mm-base-manager.c:401) ==2277== Address 0xf677d18 is 88 bytes inside a block of size 96 free'd ==2277== at 0x4C2E14B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==2277== by 0x14A1B7: port_context_unref (mm-plugin-manager.c:234) ==2277== by 0x14AB51: plugin_supports_port_ready (mm-plugin-manager.c:492) ==2277== by 0x612FD52: ??? (in /usr/lib/libgio-2.0.so.0.5200.3) ==2277== by 0x6130775: ??? (in /usr/lib/libgio-2.0.so.0.5200.3) ==2277== by 0x1AFDF8: port_probe_run_ready (mm-plugin.c:624) ==2277== by 0x612FD52: ??? (in /usr/lib/libgio-2.0.so.0.5200.3) ==2277== by 0x6130775: ??? (in /usr/lib/libgio-2.0.so.0.5200.3) ==2277== by 0x6131367: g_task_return_error_if_cancelled (in /usr/lib/libgio-2.0.so.0.5200.3) ==2277== by 0x1A9EDA: port_probe_task_return_error_if_cancelled (mm-port-probe.c:109) ==2277== by 0x1ABCD2: serial_probe_at_parse_response (mm-port-probe.c:900) ==2277== by 0x611E475: g_simple_async_result_complete (in /usr/lib/libgio-2.0.so.0.5200.3) ==2277== Block was alloc'd at ==2277== at 0x4C2CE5F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==2277== by 0x66E3028: g_malloc (in /usr/lib/libglib-2.0.so.0.5200.3) ==2277== by 0x66FAB25: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.5200.3) ==2277== by 0x66FAFB8: g_slice_alloc0 (in /usr/lib/libglib-2.0.so.0.5200.3) ==2277== by 0x14B18D: port_context_new (mm-plugin-manager.c:649) ==2277== by 0x14C4A7: device_context_port_grabbed (mm-plugin-manager.c:1182) ==2277== by 0x83831C7: ffi_call_unix64 (in /usr/lib/libffi.so.6.0.4) ==2277== by 0x8382C29: ffi_call (in /usr/lib/libffi.so.6.0.4) ==2277== by 0x64506A8: g_cclosure_marshal_generic (in /usr/lib/libgobject-2.0.so.0.5200.3) ==2277== by 0x644FEAC: g_closure_invoke (in /usr/lib/libgobject-2.0.so.0.5200.3) ==2277== by 0x64624AD: ??? (in /usr/lib/libgobject-2.0.so.0.5200.3) ==2277== by 0x646AC84: g_signal_emit_valist (in /usr/lib/libgobject-2.0.so.0.5200.3) (cherry picked from commit bbe50645916c4596cf7c7b309aac267d396801b8)
-rw-r--r--src/mm-plugin-manager.c35
1 files changed, 19 insertions, 16 deletions
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c
index 22965fdb8..35a01122c 100644
--- a/src/mm-plugin-manager.c
+++ b/src/mm-plugin-manager.c
@@ -540,25 +540,28 @@ port_context_cancel (PortContext *port_context)
mm_dbg ("[plugin manager) task %s: cancellation requested",
port_context->name);
- /* The port context is cancelled now */
- g_cancellable_cancel (port_context->cancellable);
-
- /* If the task was deferred, we can cancel and complete it right away */
- if (port_context->defer_id) {
- g_source_remove (port_context->defer_id);
- port_context->defer_id = 0;
- port_context_complete (port_context);
- return TRUE;
- }
+ /* Make sure we hold a port context reference while cancelling, as the
+ * cancellable signal handlers may end up unref-ing our last reference
+ * otherwise. */
+ port_context_ref (port_context);
+ {
+ /* The port context is cancelled now */
+ g_cancellable_cancel (port_context->cancellable);
- /* If the task was deferred until a result is suggested, we can also
- * complete it right away */
- if (port_context->defer_until_suggested) {
- port_context_complete (port_context);
- return TRUE;
+ /* If the task was deferred, we can cancel and complete it right away */
+ if (port_context->defer_id) {
+ g_source_remove (port_context->defer_id);
+ port_context->defer_id = 0;
+ port_context_complete (port_context);
+ }
+ /* If the task was deferred until a result is suggested, we can also
+ * complete it right away */
+ else if (port_context->defer_until_suggested)
+ port_context_complete (port_context);
+ /* else, the task may be currently checking support with a given plugin */
}
+ port_context_unref (port_context);
- /* The task may be currently checking support with a given plugin */
return TRUE;
}