Commit 88cc245
fix(event): drain tty fd to EAGAIN before returning from try_read
mio registers the tty fd with Interest::READABLE, which on Linux maps
to EPOLLIN | EPOLLET — edge-triggered. The previous read loop returned
as soon as the parser produced its first event, leaving any remaining
bytes in the kernel buffer. Because the edge has already been
consumed, epoll_wait will not re-fire for those leftover bytes until
new data arrives.
In practice this surfaces as the well-known "a large paste blocks
partway through and only resumes when I press a key" symptom — for
example, pasting a few KB of text from tmux's paste-buffer (which does
not use bracketed paste, so the bytes arrive as a flood of raw
keystrokes). The first ~1 KiB is parsed, the parser returns the first
event, the loop exits with bytes still in the kernel pty, and the next
epoll_wait never fires. A real keypress later creates a new edge, the
leftover bytes finally drain, and the paste appears to "continue".
Fix: keep reading until the fd returns WouldBlock or a short read
(which also indicates no more bytes are immediately available on a
tty). All resulting events are queued in the parser. Only then do we
return the first event to the caller; subsequent try_read calls drain
the queue without any extra syscalls.
No behavior change when each try_read call corresponds to a single
small input (the typical interactive case): the read loop sees a short
read and exits immediately, identical to the old fast path.1 parent c02a080 commit 88cc245
1 file changed
Lines changed: 19 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
96 | 105 | | |
97 | 106 | | |
98 | 107 | | |
| |||
102 | 111 | | |
103 | 112 | | |
104 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
105 | 121 | | |
106 | 122 | | |
107 | 123 | | |
| |||
114 | 130 | | |
115 | 131 | | |
116 | 132 | | |
| 133 | + | |
117 | 134 | | |
118 | | - | |
119 | | - | |
120 | | - | |
| 135 | + | |
| 136 | + | |
121 | 137 | | |
122 | 138 | | |
123 | 139 | | |
| |||
0 commit comments