Cancellation might not be asynchronous under certain circumstances
I made these changes to gnome-online-accounts
to simplify the code by exploiting the fact that cancellation of messages with the non-deprecated SoupSession
is meant to be asynchronous:
The soup_session_abort and soup_session_cancel_message documentation says that the response callback for the cancelled messages will be called in the next iteration of the main loop after the cancelling API has returned.
In the case of gnome-online-accounts
:
-
soup_session_abort
is called in response toGCancellable::cancelled
due to the user cancelling the enveloping asynchronous operation - the response callback frees the task data of the asynchronous operation which leads to g_cancellable_disconnect.
If soup_session_abort
doesn't invoke the response callback asynchronously, then the code will deadlock because one cannot disconnect from a GCancellable
from its GCancellable::cancelled
handler, and the above gnome-online-accounts
changes would not work.
While testing those changes, I found a way to trigger a deadlock. The backtrace looked like this:
g_cancellable_disconnect()
ews_client_autodiscover_data_free()
ews_client_autodiscover_response_cb()
- ...
soup_session_abort()
- ...
g_cancellable_cancel()
Sadly, now that I installed all the debug symbols, I have lost my magic powers to win the necessary races to trigger the deadlock. I believe it could be because of some local DNS cache, so hopefully I will be successful in the near future.
I have libsoup-2.64.2-1.fc29.x86_64
.
Here is some documentation on how to play with gnome-online-accounts
.