Skip to content

gpbs: timeout INCR transfer receive to stop pasteboard hangs - #231

Open
probonopd wants to merge 3 commits into
gnustep:masterfrom
probonopd:fix/gpbs-incr-timeout
Open

gpbs: timeout INCR transfer receive to stop pasteboard hangs#231
probonopd wants to merge 3 commits into
gnustep:masterfrom
probonopd:fix/gpbs-incr-timeout

Conversation

@probonopd

Copy link
Copy Markdown
Contributor

gpbs blocks forever in the X selection incremental (INCR) receive loop when the selection owner dies or stalls mid-transfer, making the whole pasteboard unresponsive and forcing gpbs to be killed.

Fix: wait on the X connection descriptor with a 5s deadline before each INCR chunk; on timeout abandon the transfer and discard the partial data instead of blocking on XNextEvent indefinitely.

Verified: a stalling clipboard owner now causes a nil result after exactly 5s instead of a permanent hang, and gpbs serves subsequent pasteboard requests normally.

gpbs blocks forever in the X selection incremental (INCR) receive loop
when the selection owner dies or stalls mid-transfer, making the whole
pasteboard unresponsive and forcing gpbs to be killed.

Wait on the X connection descriptor with a 5s deadline before each
INCR chunk; on timeout abandon the transfer and discard the partial
data instead of blocking on XNextEvent indefinitely.
@probonopd
probonopd requested a review from fredkiefer as a code owner August 8, 2026 06:41
The error handler is referenced in +initializePasteboard before its
definition; GCC (as used on CI) rejects the implicit declaration.
Declare it explicitly so the build succeeds everywhere.
@rfm

rfm commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

I don't know how often we want to handle multiple pasteboard requests at about the same time, but if it is a big issue then I think the solution would be to rewrite this to be asynchronous (or multithreaded with coordination on the X server comms) and handle them all at once. However, this timeout seems a good simple option.
The only real worry I have is that 5 seconds is not long enough. I remember when testing pasteboard issues with Riccardo we were using big images from Gimp, and I think Gimp advertises multiple image formats but keeps the image in one format internally, so when responding to a request it would first convert the image format and then send the image data, with the conversion taking several/many seconds. In short, I think some apps may take quite a long time to respond with the initial chunk of data due to internal conversion issues (or other reasons I suppose), so a longer timeout probably makes sense.

@probonopd

Copy link
Copy Markdown
Contributor Author

What timeout would you suggest?

@rfm

rfm commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

My best recollection is that Gimp was taking what seemed like a very long time, but not so long that we gave up ... more than 5, but less than 30. My intuition is that Gimp is an extreme case. Most apps ought to be fast enough because the data to be pasted is small, and the only thing larger than images would be things like audio/video where apps are built to stream and either cut/paste makes no sense or format conversion would be done while streaming (so the app would quickly send chunks of data rather than converting an entire video in one operation. So I think 30 seconds would be plenty long enough, and we might want it shorter than that if we want to try to avoid giving the impression that things gave hung.

Allow for big images from Gimp not to time out
@probonopd

Copy link
Copy Markdown
Contributor Author

Updated to 20.

@rmottola

Copy link
Copy Markdown
Member

@rfm yes indeed, I remember testing very long times. I also wonder what happens if there is a network in the middle, if that slows the whole timeout or only affects actual transfer times.

@probonopd I did a lot of copy&paste testing also with very big file to test multiple chunks and never got crashes, how did you get to that?

@probonopd

Copy link
Copy Markdown
Contributor Author

Had observed flaky copy&paste on the Gershwin Desktop, so I had AI analyze the code and suggest probable causes, then did a lot of manual testing.

Here is my understanding of the situation:

The problem is that clipboard data can be transferred in multiple pieces when using X11's INCR mechanism. After receiving one piece, gpbs waits for an X11 event containing the next piece. Previously, this was done directly with XNextEvent(). If the application providing the clipboard data stopped responding or exited, the expected event might never arrive, causing gpbs to wait indefinitely.

This change avoids that by checking the X11 connection with select() before calling XNextEvent(). The wait is given a finite timeout, so gpbs will eventually stop waiting if no new data arrives. When the timeout expires, the incomplete clipboard transfer is discarded rather than leaving gpbs stuck. This allows the pasteboard server to continue processing other requests.

This seems to be working for me constantly. I have been using it on my daily driver machine (Devuan) for a while now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants