aboutsummaryrefslogtreecommitdiff
path: root/src/mm-port-probe.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2017-10-05 12:32:17 +0200
committerAleksander Morgado <aleksander@aleksander.es>2017-10-05 12:37:12 +0200
commit71730509ee0f84fed250cd79c9384df5fa2f0c77 (patch)
tree97e3b067a1f3ebdc822dc30546b3b34c7133f710 /src/mm-port-probe.c
parent3e15dc15efd118a2e7af8f60727afc7fbb7db3a3 (diff)
port-probe: avoid deadlock trying to disconnect cancellable
We cannot in any way try to disconnect a GCancellable from within a cancellation handler, or we'll deadlock. Thread 1 (Thread 0x7fe98bf25700 (LWP 12079)): #0 0x00007fe98a355f36 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0 #1 0x00007fe98a7f5ac0 in g_cond_wait () from /usr/lib/libglib-2.0.so.0 #2 0x00007fe98ad14650 in g_cancellable_disconnect () from /usr/lib/libgio-2.0.so.0 #3 0x000000000045be5d in port_probe_run_context_free () #4 0x00007fe98ad519ed in g_task_finalize () from /usr/lib/libgio-2.0.so.0 #5 0x00007fe98aaaa7b3 in g_object_unref () from /usr/lib/libgobject-2.0.so.0 #6 0x000000000045b5f8 in port_probe_task_return_error_if_cancelled () #7 0x000000000045c57d in serial_probe_at_parse_response () #8 0x00007fe98ad42ed2 in g_simple_async_result_complete () from /usr/lib/libgio-2.0.so.0 #9 0x0000000000485c7d in serial_command_ready () #10 0x00007fe98ad42ed2 in g_simple_async_result_complete () from /usr/lib/libgio-2.0.so.0 #11 0x0000000000482345 in command_context_complete_and_free () #12 0x0000000000482fa5 in port_serial_got_response () #13 0x00000000004830f5 in port_serial_response_wait_cancelled () #14 0x00007fe98aaa70c5 in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0 #15 0x00007fe98aab47ce in signal_emit_unlocked_R () from /usr/lib/libgobject-2.0.so.0 #16 0x00007fe98aabb595 in g_signal_emit_valist () from /usr/lib/libgobject-2.0.so.0 #17 0x00007fe98aabb662 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0 #18 0x00007fe98ad144c5 in g_cancellable_cancel () from /usr/lib/libgio-2.0.so.0 #19 0x00007fe98aaa70c5 in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0 #20 0x00007fe98aab47ce in signal_emit_unlocked_R () from /usr/lib/libgobject-2.0.so.0 #21 0x00007fe98aabb595 in g_signal_emit_valist () from /usr/lib/libgobject-2.0.so.0 #22 0x00007fe98aabb662 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0 #23 0x00007fe98ad144c5 in g_cancellable_cancel () from /usr/lib/libgio-2.0.so.0 #24 0x000000000042e9f6 in port_context_cancel () #25 0x00007fe989b99a4c in ffi_call_unix64 () at ../src/x86/unix64.S:75 #26 0x00007fe989b994b9 in ffi_call (cif=0x7fffc41dcdb0, fn=0x42ea40 <device_context_port_released>, rvalue=<optimized out>, avalue=0x7fffc41dccd0) at ../src/x86/ffi64.c:492 #27 0x00007fe98aaa7700 in g_cclosure_marshal_generic () from /usr/lib/libgobject-2.0.so.0 #28 0x00007fe98aaa70c5 in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0 #29 0x00007fe98aab47ce in signal_emit_unlocked_R () from /usr/lib/libgobject-2.0.so.0 #30 0x00007fe98aabb595 in g_signal_emit_valist () from /usr/lib/libgobject-2.0.so.0 #31 0x00007fe98aabb662 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0 #32 0x000000000042c8f0 in mm_device_release_port () #33 0x000000000042a6cb in device_removed () #34 0x000000000042af94 in handle_kernel_event () #35 0x000000000042b356 in report_kernel_event_auth_ready () #36 0x00007fe98ad51783 in g_task_return_now () from /usr/lib/libgio-2.0.so.0 #37 0x00007fe98ad517b9 in complete_in_idle_cb () from /usr/lib/libgio-2.0.so.0 #38 0x00007fe98a7bda5e in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 #39 0x00007fe98a7bddb8 in g_main_context_iterate.isra () from /usr/lib/libglib-2.0.so.0 #40 0x00007fe98a7be042 in g_main_loop_run () from /usr/lib/libglib-2.0.so.0 #41 0x0000000000428dc4 in main () So, just clear the cancellation id before going on with the handler logic.
Diffstat (limited to 'src/mm-port-probe.c')
-rw-r--r--src/mm-port-probe.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c
index c6fa8ad0..bd003ffd 100644
--- a/src/mm-port-probe.c
+++ b/src/mm-port-probe.c
@@ -1285,10 +1285,12 @@ serial_open_at (MMPortProbe *self)
}
static void
-at_cancellable_cancel (GCancellable *main_cancellable,
- GCancellable *at_cancellable)
+at_cancellable_cancel (GCancellable *cancellable,
+ PortProbeRunContext *ctx)
{
- g_cancellable_cancel (at_cancellable);
+ /* Avoid trying to disconnect cancellable on the handler, or we'll deadlock */
+ ctx->at_probing_cancellable_linked = 0;
+ g_cancellable_cancel (ctx->at_probing_cancellable);
}
gboolean
@@ -1405,8 +1407,8 @@ mm_port_probe_run (MMPortProbe *self,
if (cancellable)
ctx->at_probing_cancellable_linked = g_cancellable_connect (cancellable,
(GCallback) at_cancellable_cancel,
- g_object_ref (ctx->at_probing_cancellable),
- g_object_unref);
+ ctx,
+ NULL);
ctx->source_id = g_idle_add ((GSourceFunc) serial_open_at, self);
return;
}