diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-10-05 12:32:17 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-10-05 12:37:12 +0200 |
commit | 71730509ee0f84fed250cd79c9384df5fa2f0c77 (patch) | |
tree | 97e3b067a1f3ebdc822dc30546b3b34c7133f710 /src/mm-port-probe.c | |
parent | 3e15dc15efd118a2e7af8f60727afc7fbb7db3a3 (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.c | 12 |
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; } |