ref: cdb35f2dc70ceabdf5ead9da99aba535224d3e2c
parent: 4e32a9fa6e58c1474f747a99083303c4a2f14ea7
author: Jacob Moody <moody@posixcafe.org>
date: Sun Jun 29 16:04:06 EDT 2025
gui-wl: avoid deadlock with clipboard With how wayland works its possible that we're sending updated clipboard content to ourselves. If so, we can't have the main dispatch proc in charge of both; once we fill the host pipe buffer we'll block on the write waiting for a reader that will never show. Instead just spin out a proc(pthread) when we're given someone to write to. This happened to work because our max snarf size was below the max of what the kernel would buffer for us. This was found as part of bumping that limit.
--- a/gui-wl/wl-cb.c
+++ b/gui-wl/wl-cb.c
@@ -447,13 +447,32 @@
.name = seat_handle_name,
};
+typedef struct {
+ int fd;
+ int len;
+ char msg[];
+} ClipWrite;
+
static void
+clipwriteproc(void *arg)
+{
+ ClipWrite *c;
+ ulong n, pos;
+
+ c = arg;
+ for(pos = 0; (n = write(c->fd, c->msg+pos, c->len-pos)) > 0 && pos < c->len; pos += n)
+ ;
+ close(c->fd);
+ free(c);
+ pexit(nil, 0);
+}
+
+static void
data_source_handle_send(void *data, struct wl_data_source *source, const char *mime_type, int fd)
{
- ulong n;
- ulong pos;
ulong len;
Wlwin *wl;
+ ClipWrite *c;
if(strcmp(mime_type, "text/plain;charset=utf-8") != 0)
return;
@@ -461,9 +480,11 @@
wl = data;
qlock(&wl->clip.lk);
len = strlen(wl->clip.content);
- for(pos = 0; (n = write(fd, wl->clip.content+pos, len-pos)) > 0 && pos < len; pos += n)
- ;
- close(fd);
+ c = malloc(sizeof(ClipWrite) + len);
+ c->fd = fd;
+ c->len = len;
+ memcpy(c->msg, wl->clip.content, len);
+ kproc("clipwriteproc", clipwriteproc, c);
qunlock(&wl->clip.lk);
}
@@ -488,10 +509,9 @@
static void
primsel_source_handle_send(void *data, struct zwp_primary_selection_source_v1 *source, const char *mime_type, int fd)
{
- ulong n;
- ulong pos;
ulong len;
Wlwin *wl;
+ ClipWrite *c;
if(strcmp(mime_type, "text/plain;charset=utf-8") != 0)
return;
@@ -499,9 +519,11 @@
wl = data;
qlock(&wl->clip.lk);
len = strlen(wl->clip.content);
- for(pos = 0; (n = write(fd, wl->clip.content+pos, len-pos)) > 0 && pos < len; pos += n)
- ;
- close(fd);
+ c = malloc(sizeof(ClipWrite) + len);
+ c->fd = fd;
+ c->len = len;
+ memcpy(c->msg, wl->clip.content, len);
+ kproc("clipwriteproc", clipwriteproc, c);
qunlock(&wl->clip.lk);
}
--
⑨