From 4c91c153cb087e1256578da1e53f002edefc9958 Mon Sep 17 00:00:00 2001
From: Nicholas Marriott <nicholas.marriott@gmail.com>
Date: Sun, 17 Feb 2013 22:28:11 +0000
Subject: [PATCH] I strongly suspect it is possible for tmux to block on detach
 in tty_raw, so make the fd blocking again much later and have tty_raw just
 retry the write a few times.

---
 tty.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/tty.c b/tty.c
index 378539ca..892960f8 100644
--- a/tty.c
+++ b/tty.c
@@ -267,8 +267,6 @@ tty_stop_tty(struct tty *tty)
 	if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1)
 		return;
 
-	setblocking(tty->fd, 1);
-
 	tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1));
 	if (tty_use_acs(tty))
 		tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS));
@@ -288,6 +286,8 @@ tty_stop_tty(struct tty *tty)
 		tty_raw(tty, "\033[?1000l");
 
 	tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP));
+
+	setblocking(tty->fd, 1);
 }
 
 void
@@ -332,7 +332,21 @@ tty_free(struct tty *tty)
 void
 tty_raw(struct tty *tty, const char *s)
 {
-	write(tty->fd, s, strlen(s));
+	ssize_t	n, slen;
+	u_int	i;
+
+	slen = strlen(s);
+	for (i = 0; i < 5; i++) {
+		n = write(tty->fd, s, slen);
+		if (n >= 0) {
+			s += n;
+			slen -= n;
+			if (slen == 0)
+				break;
+		} else if (n == -1 && errno != EAGAIN)
+			break;
+		usleep(100);
+	}
 }
 
 void