sway: Pasting into Xwayland windows occasionally stops working

  • Sway Version: 1.0-rc1-208-g679c058f (Apr 1 2019, branch 'master')

At some point during a long session pasting something copied via Wayland into Xwayland windows breaks.

When copying text from Wayland (Ctrl-C in a GTK app or wl-copy) the following happens. Trying to paste into Qt windows (Telegram) makes it freeze for a while, trying to paste into Discord (Electron) makes it freeze for a while, trying to paste into Nautilus (GTK) just doesn’t do anything. Pasting into Wayland windows and wl-paste works fine.

When copying text from X in this state, pasting into other X and Wayland windows works fine.

The issue can be solved by restarting Xwayland (by killing it).

If needed, I can try to dump a log over a long session until the bug occurs to post it here.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 49
  • Comments: 49 (33 by maintainers)

Commits related to this issue

Most upvoted comments

Most often the clipboard breaks when I paste something into Telegram Desktop (Qt). I’m not sure if Telegram is the only app causing this, and pasting into Telegram doesn’t always break the clipboard.

Writing this down to make sure it doesn’t get lost. Although I still haven’t narrowed down the true root cause, I did figure out that:

  1. What we’re dealing with appears to be a race condition. On occasion (somewhere between 1 and 30 and 1 and 100 attempts) the incr transfer actually seems to succeed just fine. Whenever it fails, it fails because QXcb deletes its requestor window, which leaves xwm hanging. I just created a PR in wlroots (swaywm/wlroots#2316) to address this particular failure. It would still be wise to add a timeout as well down the road, and that should be relatively easy. (edit: Also, I think the particular race is between the state changes occurring with xwm_data_source_read and xwm_send_incr_chunk. Not sure exactly.)

  2. Because it actually succeeds sometimes, with this patch applied you can force pasting to work by just repeating it over and over. So although it does not fix the problem, in that Qt pastes will still fail, it should be a pretty big quality of life improvement, except…

  3. I suspect that aside from the outgoing incr issue I have discovered, there is likely issues with incoming incr transfers, thus explaining why Wayland clients also have clipboard problems on occasion. Therefore, it is possible the same mitigations may be desired for incoming transfers as well. I’m trying to take a conservative approach though as I am unable to reproduce every issue I’ve witnessed inside of a test environment at this point. (I do reliably have a way to cause the outgoing selection issue.)

I’m back into debugging this. I’ve managed to narrow down some of the issues that are going on.

Wlroots only allows there to be one active outgoing Xwayland transfer at a time. For some reason, Qt’s QXcb code for incremental transfers is causing the Xwayland transfer to stall forever. The bug is probably in wlroots and not Sway. I still have not determined the root cause of the stall, but I’m trying to map out exactly what’s going on right now.

Aside from actually fixing this issue causing it to stall, I wonder if there’s any sense in trying to improve the failure modes for this case in wlroots. Like, perhaps if the requestor disappears, the transfer can be removed from the queue? Maybe a (long) timeout can be added? etc.

This has (hopefully, fingers crossed) been resolved in wlroots master. Please open a new ticket against wlroots, with fresh logs, for any continuing clipboard misbehaviors.

I do not know if this is related but I noticed something similar a few weeks ago while experimenting with the experimental wayland backend of Firefox (i.e. the upstream version with MOZ_ENABLE_WAYLAND=1). In my case the issue only happened while copying from Firefox to a X11 window on another workspace (xterm, emacs, …):

  1. Start MOZ_ENABLE_WAYLAND=1 firefox (and check that the Wayland backend is effectively used).
  2. Copy text in Firefox
  3. DO NOT GIVE FOCUS TO ANY X11 WINDOW.
  4. Switch workspace
  5. Try to paste in a X11 window (Xterm, Emacs, …)

Effect: The selected text is not properly pasted and in some cases emacs freezes.

Step 3 is important. If I gave focus to any X11 window before witching workspace then everything worked fine so I assumed that the issue was with the Firefox window somehow refusing to provide its selection while not visible.

I cannot reproduce it with the current version of Firefox so that specific issue was probably fixed by a recent upgrade of sway or more likely of Firefox.

A number of Xwayland clipboard-related fixes recently made it into wlroots master:

I think these should help with some remaining cases where the clipboard can get stuck.

A more concrete, pending fix that I’d appreciate anyone willing to test is https://github.com/swaywm/wlroots/pull/2707. I’m currently dogfooding it myself and it (seemingly) works, but the clipboard code is gnarly and hard to exercise all the corner cases of.

More testers would be appreciated to shake out any remaining bugs 😃

  1. What we’re dealing with appears to be a race condition.

I’m not a sway user, but I found this issue when surfing some tdesktop issues and I think I can give some light:

Yeah, there are a bug in Qt XCB backend that closes window earlier than transfer is completed: https://bugreports.qt.io/browse/QTBUG-56595 And there are even a duplicate bug report (with some additions like losing of the alpha channel): https://bugreports.qt.io/browse/QTBUG-79656

This bug sits in Qt for years and there were a lot of angry reports in Telegram: https://github.com/telegramdesktop/tdesktop/issues/5730 https://github.com/telegramdesktop/tdesktop/issues/6952 https://github.com/telegramdesktop/tdesktop/issues/7223 https://github.com/telegramdesktop/tdesktop/issues/7292. I tried to give some live to the Qt bug report, but I failed and implemented pasting images in tdesktop in gtk.

This issue occurs in most times when copying a big image from gimp and pasting to Qt apps: gimp crashes with BadWindow error.

I guess that just no one in Qt knows why this is happening and how to fix this 🙈

Sorry, still working on this, I just got a bit excited from finally figuring out some additional details.

However, when I get stuck in this state, I’ve noticed something else rather strange… wl-paste also starts locking up. It stalls on a wait4

It waits for the cat it spawns to read the data from the pipe. If it stalls, that means whoever writes to the other end of the pipe doesn’t finish writing.

Can you also reproduce this by copying large amounts of text? And does this also happen when copying not from wl-copy?

Yes, that’s exactly what I decided to try next. You can reproduce it for yourself with:

kwrite -platform xcb &
</dev/urandom tr -dc 'a-zA-Z0-9~!@#$%^&*_-' | head -c $((2**16 - 1)) # This one works
</dev/urandom tr -dc 'a-zA-Z0-9~!@#$%^&*_-' | head -c $((2**16)) # Now kwrite should fail to paste.

So it looks like 64 KiB causes this. Interestingly, it only happens with Qt apps seemingly. If I try an Electron app, it can happily keep going (I went all the way to 64 MiB with no problem.) So it seems XWayland and Sway alone are not the culprits.

edit: Also yes regarding non-wl-copy - FWIW, I have the exact same problem when I copy out of Firefox in Wayland. I can check xclip as well. I think it only happens with Wayland copies.

edit 2: I suspect the 64 KiB number is a result of Qt’s QXcbClipboard implementation. Specifically clipboardReadIncrementalProperty. Maybe incremental property reads are broken in wlroots xwayland somehow. I need to rest so I’ll pick up later.

Firefox freezes when it’s not visible. This is not a sway bug, this is a Firefox bug.

Thanks @jchv 😃

So far I haven’t run into cases where I can’t regain control of the clipboard without restarting Xwayland, which is nice. Usually the clipboard becomes responsive again after copying some other text into it, at worst the misbehaving application has to be restarted. (I know the misbehaving application is always fcitx in my case.)

I have been able to induce some contrived compositor crashes by holding down <kbd>Ctrl</kbd>+<kbd>V</kbd> for a long time while fcitx hangs, but haven’t encountered “real” issues in my testing so far.

Trace 1
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f191049dbd3 in xwm_selection_transfer_destroy_outgoing (transfer=0x1104ee32c) at ../xwayland/selection/outgoing.c:77

warning: Source file is more recent than executable.
77		if (was_first && !wl_list_empty(&selection->outgoing)) {
[Current thread is 1 (Thread 0x7f190ef2a500 (LWP 23212))]
warning: File "/home/xyene/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
	add-auto-load-safe-path /home/xyene/.gdbinit
line to your configuration file "/root/.gdbinit".
To completely disable this security protection add
	set auto-load safe-path /
line to your configuration file "/root/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual.  E.g., run from the shell:
	info "(gdb)Auto-loading safe path"
(gdb) bt full
#0  0x00007f191049dbd3 in xwm_selection_transfer_destroy_outgoing (transfer=0x1104ee32c) at ../xwayland/selection/outgoing.c:77
        selection = 0xffffffff00000020
        was_first = false
#1  0x00007f19104ee402 in wl_event_loop_dispatch () from /lib/x86_64-linux-gnu/libwayland-server.so.0
No symbol table info available.
#2  0x00007f19104ec9e5 in wl_display_run () from /lib/x86_64-linux-gnu/libwayland-server.so.0
No symbol table info available.
#3  0x0000563596ffd122 in server_run (server=0x56359706f2c0 <server>) at ../sway/server.c:244
No locals.
#4  0x0000563596ffc606 in main (argc=3, argv=0x7fffa66eae68) at ../sway/main.c:412
        verbose = 1
        debug = 1
        validate = 0
        allow_unsupported_gpu = 0
        long_options = {{name = 0x56359705212c "help", has_arg = 0, flag = 0x0, val = 104}, {name = 0x563597052131 "config", has_arg = 1, flag = 0x0, val = 99}, {name = 0x563597052138 "validate", has_arg = 0, flag = 0x0, val = 67}, {name = 0x563597052141 "debug", has_arg = 0, flag = 0x0, val = 100}, {name = 0x563597052147 "version", 
            has_arg = 0, flag = 0x0, val = 118}, {name = 0x56359705214f "verbose", has_arg = 0, flag = 0x0, val = 86}, {name = 0x563597052157 "get-socketpath", has_arg = 0, flag = 0x0, val = 112}, {name = 0x563597052166 "unsupported-gpu", has_arg = 0, flag = 0x0, val = 117}, {name = 0x563597052176 "my-next-gpu-wont-be-nvidia", 
            has_arg = 0, flag = 0x0, val = 117}, {name = 0x0, has_arg = 0, flag = 0x0, val = 0}}
        config_path = 0x0
        usage = 0x563597051b88 "Usage: sway [options] [command]\n\n  -h, --help", ' ' <repeats 13 times>, "Show help message and quit.\n  -c, --config <config>  Specify a config file.\n  -C, --validate         Check the validity of the config file, th"...
        c = -1

An interesting note is that, unless I’m totally misunderstanding the source, Weston pre-empts any ongoing transfers on receipt of a new XCB_SELECTION_REQUEST:

https://gitlab.freedesktop.org/wayland/weston/-/blob/master/xwayland/selection.c#L591-593

Sommelier does the same (presumably it’s based on Weston, or they’re both based on the same thing?):

https://chromium.googlesource.com/chromiumos/platform2/+/master/vm_tools/sommelier/sommelier.c#2878

That seems to me like a compositor-global version of what https://github.com/swaywm/wlroots/commit/7bb9d48dd1383b688c8fefbbb08c552c3cc33c18 does: rather than limit to one request per window, it limits to one request per compositor, and cancels stalled/ongoing ones as needed…? I’m not sure how it doesn’t end up with applications stepping on each other as they repeatedly race for the clipboard, though. I mean, clearly it works in practice so it must work, or I may be misunderstanding how it works. Preempting transfers certainly would prevent any clipboard hangs. I haven’t checked what Mutter does.

(Of course, this doesn’t really answer why fcitx/Qt hang on incremental transfers in the first place, but I’m not super keen on digging into Qt right now.)

Same issue. In ps aux output I see wl-copy and cat /tmp/wl-copy... processes. If you try paste to Telegram or Chrome window will freeze for few second. So even text is impossible to paste.

Having the same issue (wl-clipboard works fine on wayland windows, but can’t paste on xwayland windows like anki, firefox and chrome).

Note that pkill Xwayland will restore text copy/pasting functionality on xwayland windows, but as soon as I try to take a screenshot (grim -g \"$(slurp)" - | wl-copy), it breaks again.

I confirm that taking a screenshot breaks it. Killing Xwayland also restores copy/pasting functionality!

Having the same issue (wl-clipboard works fine on wayland windows, but can’t paste on xwayland windows like anki, firefox and chrome).

Note that pkill Xwayland will restore text copy/pasting functionality on xwayland windows, but as soon as I try to take a screenshot (grim -g \"$(slurp)" - | wl-copy), it breaks again.

@RPigott thanks. My issue was the one Xyene mentioned. Upgrading to gtk±3.24.24 fixed it.

Ah, thanks for pointing that out. By “the commit”, I mean I’m using your PR(and appreciate it).

https://github.com/swaywm/wlroots/pull/2428 should help for at least some of the issues discussed here.

Unfortunately, I’ve been able to consistently reproduce this in GNOME + Wayland as well, leading me to believe this is more complicated than just Sway/wlroots. 😦

I’m very sure all my Qt programs have wayland windows. Just to be clear, I do have xwayland-using programs as well, and when I posted my first comment claiming I have an issue, it was from being unable to paste in an xwayland window (VSCode) from a wayland window (firefox).

Also note that this thread already has one other non-Qt source of this issue - https://github.com/swaywm/sway/issues/4007#issuecomment-617448193 . I do take screenshots with grim piped to wl-copy myself, so it’s possible my trigger was the same as that comment, but I can’t repro it at the moment.

Something strange is going on.

I tried to reproduce this by doing a loop of grim, wl-copy, xclip, etc. in a nested SwayWM session in an effort to reproduce the problem, but nothing really seems to do it.

However, when I get stuck in this state, I’ve noticed something else rather strange… wl-paste also starts locking up. It stalls on a wait4:

socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/run/user/1000/wayland-0"}, 27) = 0
sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\1\0\0\0\1\0\f\0\2\0\0\0\1\0\0\0\0\0\f\0\3\0\0\0", iov_len=24}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 24
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\2\0\0\0\0\0\34\0\1\0\0\0\7\0\0\0wl_shm\0\0\1\0\0\0\2\0\0\0"..., iov_len=4096}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 1360
sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\2\0\0\0\0\0 \0\1\0\0\0\7\0\0\0wl_shm\0\0\1\0\0\0\4\0\0\0"..., iov_len=384}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 384
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\4\0\0\0\0\0\f\0\0\0\0\0\4\0\0\0\0\0\f\0\1\0\0\0\4\0\0\0\0\0\f\0"..., iov_len=2736}, {iov_base="", iov_len=1360}], msg_iovlen=2, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 104
sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\t\0\0\0\1\0\20\0\3\0\0\0\v\0\0\0", iov_len=16}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 16
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\3\0\0\0\0\0\f\0\0\0\0\377\0\0\0\377\0\0\30\0\n\0\0\0text/htm"..., iov_len=2632}, {iov_base="", iov_len=1464}], msg_iovlen=2, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 1004
pipe([4, 5])                            = 0
fcntl(5, F_DUPFD_CLOEXEC, 0)            = 6
sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0\0\0\377\0\0\30\0\n\0\0\0image/png\0\0\0\1\0\0\0\0\0\f\0"..., iov_len=44}], msg_iovlen=1, msg_control=[{cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, cmsg_data=[6]}], msg_controllen=20, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 44
close(6)                                = 0
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\f\0\0\0\0\0\f\0F\235\0\0\1\0\0\0\1\0\f\0\f\0\0\0", iov_len=1628}, {iov_base="", iov_len=2468}], msg_iovlen=2, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 24
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7feab2d670d0) = 18837
close(4)                                = 0
close(5)                                = 0
wait4

I can, of course, still paste to some native Wayland apps, so this is pretty weird.

In fact, if I go then restart an XWayland program while still in the broken state, it will still be broken. Only if I go copy something else first, does it resolve. Even another screenshot can work!

Then I finally noticed that the issue actually appears to be size related. If I take a bunch of tiny screenshots, everything seems fine. It’s when my screenshots get larger that things start to mess up.

Finally, I was able to reproduce the problem in my script by doing a full screenshot of an application instead of a small screenshot of mostly blank space. Now, I can see broken pasting in Krita inside the nested session reliably. It just takes one screenshot that’s too large and everything seems to topple. For some reason, Krita behaves slightly better in the nested session than it does for me normally.

It seems like it really does depend on the actual size of the clipboard in bytes rather than dimensions. I can take large screenshots of pure white without XWayland apps or wl-paste acting up.

Krita in a normal session acts a bit stranger when in the error case. In the nested session, it locks up once for a period of time after copying, then locks up again for a period of time when trying to paste. However, in my real session, when this happens, Krita continues to be locked up, only updating every 10-20 seconds or so, until something else is copied into the clipboard. I am chalking this up to interplay between applications for now, but it might be worth exploring if none of the existing avenues prove useful.

Can others confirm that the size of the clipboard is the issue and not necessarily the way it’s copied? To confirm, in a pristine state, try taking a few small screenshots of white and then try taking a larger screenshot of something more complicated, and see at what point things start to misbehave.

Yep, I have the same issue with the right click menu in Telegram when the clipboard is broken. I suspect it’s because Telegram attempts to paste something to decide whether to show the “Paste” menu item active or inactive, and that already triggers the issue.

I’m also experiencing something similar, but also opening the right-click menu takes forever. Slack is my biggest offender.