git: drawterm

Download patch

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);
 }
 
--