terminal: work around macos poll() bug
On macos the builtin "add -p" does not handle keys that generate escape sequences because poll() does not work with terminals there. Switch to using select() on non-windows platforms to work around this. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Phillip Wood committed
Mar 16, 2022 at 18:54 UTC
6606d99bae4161289d498b51a21acd11aa09e6ef
1 file changed
+36
-6
compat/terminal.c
+36
-6
@@ -92,6 +92,31 @@ static int enable_non_canonical(enum save_term_flags flags)
92
return disable_bits(flags, ICANON | ECHO);
93
}
94
95
+/*
96
+ * On macos it is not possible to use poll() with a terminal so use select
97
+ * instead.
98
+ */
99
+static int getchar_with_timeout(int timeout)
100
+{
101
+ struct timeval tv, *tvp = NULL;
102
+ fd_set readfds;
103
+ int res;
104
+
105
+ if (timeout >= 0) {
106
+ tv.tv_sec = timeout / 1000;
107
+ tv.tv_usec = (timeout % 1000) * 1000;
108
+ tvp = &tv;
109
+ }
110
+
111
+ FD_ZERO(&readfds);
112
+ FD_SET(0, &readfds);
113
+ res = select(1, &readfds, NULL, NULL, tvp);
114
+ if (res <= 0)
115
+ return EOF;
116
+
117
+ return getchar();
118
+}
119
+
120
#elif defined(GIT_WINDOWS_NATIVE)
121
122
#define INPUT_PATH "CONIN$"
@@ -257,6 +282,16 @@ static int mingw_getchar(void)
282
}
283
#define getchar mingw_getchar
284
285
+static int getchar_with_timeout(int timeout)
286
+{
287
+ struct pollfd pfd = { .fd = 0, .events = POLLIN };
288
+
289
+ if (poll(&pfd, 1, timeout) < 1)
290
+ return EOF;
291
+
292
+ return getchar();
293
+}
294
+
295
#endif
296
297
#ifndef FORCE_TEXT
@@ -407,12 +442,7 @@ int read_key_without_echo(struct strbuf *buf)
442
* half a second when we know that the sequence is complete.
443
*/
444
while (!is_known_escape_sequence(buf->buf)) {
410
- struct pollfd pfd = { .fd = 0, .events = POLLIN };
411
-
412
- if (poll(&pfd, 1, 500) < 1)
413
- break;
414
-
415
- ch = getchar();
445
+ ch = getchar_with_timeout(500);
446
if (ch == EOF)
447
break;
448
strbuf_addch(buf, ch);