[Wayland] [Niri] Copy image can cause hang/freeze
Categories
(Core :: Widget: Gtk, defect, P3)
Tracking
()
People
(Reporter: pixelhamsteryt, Unassigned)
References
(Blocks 2 open bugs)
Details
Attachments
(4 files)
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0
Steps to reproduce:
Prerequisites:
- Niri compositor on wayland
- Find a webpage with an image
- Right click the image
- Click
Copy Imagein the context menu - Paste the image outside of firefox/have a clipboard manager running that tries to get the contents.
Reproduction success% is quite low :/, but high enough to be really annoying, seems to happen more often when I've been using the browser for a while and large images.
Actual results:
Firefox freezes, image contents are not pasted.
wl-paste -l does show the image mime types so the offer itself was.
I added a WAYLAND_DEBUG=1 log as an attachment.
When attaching gdb I had no debug symbols, so I just detached. Detaching caused firefox to become responsive again.
Please let me know if I can provide better logs somehow, MOZ_LOG=Clipboard:5 wasn't printing anything to stdout for me
Expected results:
Firefox does not freeze and transfers the image data to the requesting application.
Comment 1•1 year ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::Widget: Gtk' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Comment 2•1 year ago
|
||
Please run with WAYLAND_DEBUG=1 MOZ_LOG="WidgetClipboard:5" env variables and attach the log here.
Thanks.
| Reporter | ||
Comment 3•1 year ago
|
||
WAYLAND_DEBUG=1 MOZ_LOG="WidgetClipboard:5" firefox 2> firefox.log snippet around the hang
Comment 4•1 year ago
|
||
Looks like the compositor itself is frozen. Can you try to copy the image directly to wayland clipboard? by
wl-copy < image_file
| Reporter | ||
Comment 5•1 year ago
|
||
I was able to repro the hang again:
- The compositor does not appear to be frozen.
- It is also single threaded so a block in the comp would be noticeable I was told.
- wl-copy on the image worked fine during the hang
I can attach a screen recording if desired
Updated•1 year ago
|
Comment 6•1 year ago
|
||
Please run latest Firefox nightly with clean profile:
https://fedoraproject.org/wiki/How_to_debug_Firefox_problems#Testing_Mozilla_Nightly_binaries
And if Firefox freeze, try to get backtrace of it:
https://fedoraproject.org/wiki/Debugging_guidelines_for_Mozilla_products#Application_freeze
Thanks.
| Reporter | ||
Comment 7•1 year ago
|
||
I'm on arch linux, thus I adapted the fedora guide a bit to what I thought to be correct.
Got ff nightly from https://download-installer.cdn.mozilla.net/pub/firefox/nightly/latest-mozilla-central/firefox-136.0a1.en-US.linux-x86_64.tar.xz
I ran firefox-bin from the extracted files.
Was able to reproduce quickly and got a full backtrace with
merlijn@mimic ~ % pidof firefox-bin
160017 160011 159353 158775 158745 153695 153689 153673 153601 153537 153529 153513 153487 153405
merlijn@mimic ~ % sudo gdb --pid=153405
- set logging on crash_bt.log and print DumpJSStack() gave warnings on my gdb.
thread apply all bt fulldumped its output into stdout so I copied it into the attached file, I hope it's the same/what you were looking for.
Comment 8•1 year ago
|
||
Yes, that's what I need. This may be relevant:
#0 0x0000706ad091b7dd in write () at /usr/lib/libc.so.6
#1 0x0000706acc34d9de in ??? () at /usr/lib/libgio-2.0.so.0
#2 0x0000706acc30e285 in ??? () at /usr/lib/libgio-2.0.so.0
#3 0x0000706acc30e3ed in ??? () at /usr/lib/libgio-2.0.so.0
#4 0x0000706acc307747 in g_output_stream_write_async () at /usr/lib/libgio-2.0.so.0
#5 0x0000706acce42f29 in ??? () at /usr/lib/libgdk-3.so.0
#6 0x0000706acc87ecc7 in ??? () at /usr/lib/libgtk-3.so.0
#7 0x0000706acc6739aa in ??? () at /usr/lib/libgtk-3.so.0
#8 0x0000706acc482e1c in ??? () at /usr/lib/libgobject-2.0.so.0
#9 0x0000706acc482f32 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#10 0x0000706acc482ff4 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#11 0x0000706acc95a7cd in ??? () at /usr/lib/libgtk-3.so.0
#12 0x0000706acc7e7c3f in gtk_main_do_event () at /usr/lib/libgtk-3.so.0
#13 0x0000706accdf9457 in ??? () at /usr/lib/libgdk-3.so.0
#14 0x0000706acce33e80 in ??? () at /usr/lib/libgdk-3.so.0
#15 0x0000706acc50d559 in ??? () at /usr/lib/libglib-2.0.so.0
#16 0x0000706acc570257 in ??? () at /usr/lib/libglib-2.0.so.0
#17 0x0000706acc50ca55 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
Can you please install debug packages for libgdk-3.so.0 / libgio-2.0.so.0 and try again? We need function names for it.
Thanks.
| Reporter | ||
Comment 9•1 year ago
|
||
I've added the backtrace with gdk + gio symbols
Comment 10•1 year ago
|
||
Awesome, Thanks. There's the issue:
#0 0x00007bfff211b5dd in write () at /usr/lib/libc.so.6
#1 0x00007bffedb4d9de in g_unix_output_stream_write (stream=0x7bffad1d70d0 [GUnixOutputStream], buffer=0x7bff8ec00000, count=7921513, cancellable=0x0, error=0x7ffe3094b180) at ../glib/gio/gunixoutputstream.c:363
errsv = <optimized out>
unix_stream = <optimized out>
res = -1
poll_fds = {{fd = 192, events = 4, revents = 4}, {fd = 2030838016, events = 28703, revents = 0}}
nfds = <optimized out>
poll_ret = 1
#2 0x00007bffedb0e285 in write_async_pollable (stream=stream@entry=0x7bffad1d70d0, task=task@entry=0x7bffadfde280 [GTask]) at ../glib/gio/goutputstream.c:2428
error = 0x0
op = 0x7bffa9d73ca0
count_written = <optimized out>
#3 0x00007bffedb0e3ed in g_output_stream_real_write_async (stream=0x7bffad1d70d0 [GUnixOutputStream], buffer=0x7bff8ec00000, count=7921513, io_priority=<optimized out>, cancellable=<optimized out>, callback=0x7bffedb07430 <async_ready_write_callback_wrapper>, user_data=0x7bffa58a4340) at ../glib/gio/goutputstream.c:2471
task = 0x7bffadfde280 [GTask]
op = 0x7bffa9d73ca0
#4 0x00007bffedb07747 in g_output_stream_write_async (stream=0x7bffad1d70d0 [GUnixOutputStream], buffer=0x7bff8ec00000, count=7921513, io_priority=io_priority@entry=0, cancellable=0x7bffac8fe460 [GCancellable], callback=0x7bffee6372b0 <async_write_data_cb>, user_data=0x7bffa801fac0) at ../glib/gio/goutputstream.c:1067
class = <optimized out>
error = 0x0
task = 0x7bffa58a4340 [GTask]
#5 0x00007bffee643f29 in async_write_data_write (write_data=<optimized out>) at ../gtk/gdk/wayland/gdkselection-wayland.c:819
buf_len = <optimized out>
buf = <optimized out>
buf_len = <optimized out>
buf = <optimized out>
#6 stored_selection_notify_write (stored_selection=<optimized out>) at ../gtk/gdk/wayland/gdkselection-wayland.c:398
write_data = <optimized out>
i = 1
#7 gdk_wayland_selection_store (window=<optimized out>, type=0x5f, mode=GDK_PROP_MODE_REPLACE, data=0x7bff84c00000 "\211PNG\r\n\032\n", len=<optimized out>) at ../gtk/gdk/wayland/gdkselection-wayland.c:907
display = <optimized out>
selection = 0x7bfff1efc4c0
stored_selection = 0x7bffaf06e6c0
display = <optimized out>
selection = <optimized out>
stored_selection = <optimized out>
#8 gdk_wayland_window_change_property (property=<optimized out>, window=<optimized out>, type=0x5f, format=<optimized out>, mode=GDK_PROP_MODE_REPLACE, data=0x7bff84c00000 "\211PNG\r\n\032\n", nelements=7921513) at ../gtk/gdk/wayland/gdkwindow-wayland.c:4879
Gtk3 / clipboard code writes data to Wayland compositor but the write is blocked (see the freeze at g_unix_output_stream_write()). Looks like a Niri bug to me - but unfortunately Firefox doesn't support async clipboard so you see freeze if compositor fails to read clipboard data.
Comment 11•1 year ago
|
||
niri doesn't read/write clipboard and all it does just exchanges fds, like protocol intends, so it's likely just other end blocked, and thus blocked firefox. In general making non blocking reads and polling via the loop sounds like how it should be done, relying on write to not block sounds just bad, since if you paste to yourself some large data (and it ends up going to wayland clipboard), you'll likely block without async read/write in place.
| Reporter | ||
Comment 12•1 year ago
|
||
I found out that the responsible program was ironbar, a statusbar that I use (it has a clipboard history widget that always runs its listener in the background).
In ironbar's case this was due to a race condition.
-> Firefox sends 2 selections immediately after each-other when I copy 1 image.
-> Ironbar was calling .receive(..) on both offers, causing firefox to get the send(..) event.
-> But Ironbar was using an event-loop with blocking reads and that loop would get stuck on the first read and never try reading the second one.
Imo when reading https://wayland.app/protocols/wayland#wl_data_offer:request:receive both are at fault for
- in firefox's case being unable to write to both fds at the same time
- in ironbar's case not reading both at the same time.
I'm also unsure why firefox has to create 2 sources for the same copied image ?
In the meantime I've made a pr to ironbar to do the reading in a non-blocking way. But it'd of course be nice if firefox could also make their side more resilient :)
Let me know if you need more info
Description
•