New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GTK4] Ensure that clipboard read operations work synchronously #20709
base: main
Are you sure you want to change the base?
[GTK4] Ensure that clipboard read operations work synchronously #20709
Conversation
https://bugs.webkit.org/show_bug.cgi?id=265088 Reviewed by NOBODY (OOPS!). Often clipboard operations are triggered as a result of a button press event, which is handled with synchronous messages between web and UI process. However, GTK4 clipboard reads are asynchronous, and this can easily cause deadlocks when the UI process is both waiting for the press event to be handled by the web process before returning to the main loop and the GTK4 clipboard is waiting for the GAsyncReadyCallback to read from its stream at the same time, before allowing WebKit's pasteboard to finish and let the press event to finish being handled. This explains why many of the GTK4 pasteboard and clipboard tests are currently timing out -- the UI process is in a deadlock state. This deadlock can be prevented by using a GMainLoop to make sure that the GTK Clipboard will call the GAsyncReadyCallback for the clipboard operation in time, without deadlocking. * Source/WebKit/UIProcess/gtk/ClipboardGtk4.cpp: (WebKit::ReadTextAsyncData::ReadTextAsyncData): (WebKit::Clipboard::readText): (WebKit::ReadBufferAsyncData::ReadBufferAsyncData): (WebKit::Clipboard::readBuffer):
EWS run on current version of this PR (hash ac10a38) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, nested main loops are inherently very risky and error-prone. For example:
do_thing_async(async_cb);
do_another_thing_that_triggers_clipboard_read(); // <-- now async_cb may be surprisingly called here!
do_thing_required_for_async_cb_to_not_break(); // looks safe, but isn't
Programmers don't generally expect callbacks to be invoked before the next iteration of the current main loop. This is why gtk_dialog_run() was removed from GTK. Here's a recent example where this same pattern used in Epiphany caused a real bug.
This is probably fixable though. If you create your own temporary GMainContext here and push it thread default, you can run a main loop that handles only the clipboard operation and won't execute other code. Then after the call to g_main_loop_run(), pop thread default and unref the GMainContext. The question is which main context the gdk_clipboard_read_text_async() callback will be invoked on. It should hopefully be the main context that was thread-default at the time the operation started, in which case this strategy will work fine. If not, we have a problem and might need to change GdkClipboard.
I tried this and the outcome is that most tests deadlock. I didn't have time to debug that yet though (update: silly me, I forgot to use this new main context for the temporary main loop π€¦). Maybe I should explain a bit more extensively what the problem is in the bug report, but in a nutshell the original problem happens because
The problem is on the other side of the operation (reading from that stream). This would happen in the clipboard async callback. But the callback is not called quite yet. |
So, are we good then? |
BTW there is some documentation here that explains the danger I'm warning about, in the section "Using GMainContext in a Library":
|
Not quite, other tests block at a later stage (during splicing of the returned stream into a memory buffer stream). |
ac10a38
ac10a38