summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Faure <billiob@gmail.com>2019-12-04 23:12:52 +0100
committerBoris Faure <billiob@gmail.com>2019-12-04 23:13:30 +0100
commitb76bbbe45507e2c1c62e38b60f12c09eef176e15 (patch)
treea40838950e667dfd4270d8f31d1bd8d44535efca
parente1f3a4d486f66eb85ef915809aa8a0a8878491f6 (diff)
termpty: better handle writes
- Use the event loop - Check for EINTR/EAGAIN This fixes pasting large amount of data. Closes T4712
-rw-r--r--src/bin/termpty.c135
-rw-r--r--src/bin/termpty.h2
-rw-r--r--src/bin/tyfuzz.c10
3 files changed, 91 insertions, 56 deletions
diff --git a/src/bin/termpty.c b/src/bin/termpty.c
index ccc05c5..502aa90 100644
--- a/src/bin/termpty.c
+++ b/src/bin/termpty.c
@@ -225,35 +225,13 @@ _pty_size(Termpty *ty)
225} 225}
226 226
227static Eina_Bool 227static Eina_Bool
228_fd_read_do(Termpty *ty, Ecore_Fd_Handler *fd_handler, Eina_Bool false_on_empty) 228_handle_read(Termpty *ty, Eina_Bool false_on_empty)
229{ 229{
230 char buf[4097]; 230 char buf[4097];
231 Eina_Unicode codepoint[4097]; 231 Eina_Unicode codepoint[4097];
232 int len, i, j, reads; 232 int len, i, j, reads;
233 unsigned int k; 233 unsigned int k;
234 234
235 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
236 {
237 DBG("error while reading from tty slave fd");
238 ty->hand_fd = NULL;
239 return ECORE_CALLBACK_CANCEL;
240 }
241 if (ty->fd == -1)
242 {
243 ty->hand_fd = NULL;
244 return ECORE_CALLBACK_CANCEL;
245 }
246
247/* it seems the BSDs can not read from this side of the pair if the other side
248 * is closed */
249#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__)
250 if (ty->pid == -1)
251 {
252 ty->hand_fd = NULL;
253 return ECORE_CALLBACK_CANCEL;
254 }
255#endif
256
257 // read up to 64 * 4096 bytes 235 // read up to 64 * 4096 bytes
258 for (reads = 0; reads < 64; reads++) 236 for (reads = 0; reads < 64; reads++)
259 { 237 {
@@ -278,7 +256,8 @@ _fd_read_do(Termpty *ty, Ecore_Fd_Handler *fd_handler, Eina_Bool false_on_empty)
278 } 256 }
279 close(ty->fd); 257 close(ty->fd);
280 ty->fd = -1; 258 ty->fd = -1;
281 if (ty->hand_fd) ecore_main_fd_handler_del(ty->hand_fd); 259 if (ty->hand_fd)
260 ecore_main_fd_handler_del(ty->hand_fd);
282 ty->hand_fd = NULL; 261 ty->hand_fd = NULL;
283 return ECORE_CALLBACK_CANCEL; 262 return ECORE_CALLBACK_CANCEL;
284 } 263 }
@@ -337,16 +316,19 @@ _fd_read_do(Termpty *ty, Ecore_Fd_Handler *fd_handler, Eina_Bool false_on_empty)
337// DBG("---------------- handle buf %i", j); 316// DBG("---------------- handle buf %i", j);
338 termpty_handle_buf(ty, codepoint, j); 317 termpty_handle_buf(ty, codepoint, j);
339 } 318 }
340 if (ty->cb.change.func) ty->cb.change.func(ty->cb.change.data); 319 if (ty->cb.change.func)
320 ty->cb.change.func(ty->cb.change.data);
341#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) 321#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS)
342 if (len <= 0) 322 if (len <= 0)
343 { 323 {
344 ty->exit_code = 0; 324 ty->exit_code = 0;
345 ty->pid = -1; 325 ty->pid = -1;
346 326
347 if (ty->hand_exe_exit) ecore_event_handler_del(ty->hand_exe_exit); 327 if (ty->hand_exe_exit)
328 ecore_event_handler_del(ty->hand_exe_exit);
348 ty->hand_exe_exit = NULL; 329 ty->hand_exe_exit = NULL;
349 if (ty->hand_fd) ecore_main_fd_handler_del(ty->hand_fd); 330 if (ty->hand_fd)
331 ecore_main_fd_handler_del(ty->hand_fd);
350 ty->hand_fd = NULL; 332 ty->hand_fd = NULL;
351 ty->fd = -1; 333 ty->fd = -1;
352 ty->slavefd = -1; 334 ty->slavefd = -1;
@@ -355,14 +337,82 @@ _fd_read_do(Termpty *ty, Ecore_Fd_Handler *fd_handler, Eina_Bool false_on_empty)
355 return ECORE_CALLBACK_CANCEL; 337 return ECORE_CALLBACK_CANCEL;
356 } 338 }
357#endif 339#endif
358 if ((false_on_empty) && (len <= 0)) return ECORE_CALLBACK_CANCEL; 340 if ((false_on_empty) && (len <= 0))
359 return EINA_TRUE; 341 return ECORE_CALLBACK_CANCEL;
342
343 return ECORE_CALLBACK_RENEW;
344}
345
346static Eina_Bool
347_handle_write(Termpty *ty)
348{
349 struct ty_sb *sb = &ty->write_buffer;
350 ssize_t len;
351
352 if (!sb->len)
353 return ECORE_CALLBACK_RENEW;
354
355 len = write(ty->fd, sb->buf, sb->len);
356 if (len < 0 && (errno != EINTR && errno != EAGAIN))
357 {
358 ERR(_("Could not write to file descriptor %d: %s"),
359 ty->fd, strerror(errno));
360 return ECORE_CALLBACK_CANCEL;
361 }
362 ty_sb_lskip(sb, len);
363
364 if (!sb->len)
365 ecore_main_fd_handler_active_set(ty->hand_fd,
366 ECORE_FD_ERROR |
367 ECORE_FD_READ);
368
369 return ECORE_CALLBACK_RENEW;
360} 370}
361 371
362static Eina_Bool 372static Eina_Bool
363_cb_fd_read(void *data, Ecore_Fd_Handler *fd_handler) 373_fd_do(Termpty *ty, Ecore_Fd_Handler *fd_handler, Eina_Bool false_on_empty)
364{ 374{
365 return _fd_read_do(data, fd_handler, EINA_FALSE); 375 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
376 {
377 DBG("error while doing I/O on tty slave fd");
378 ty->hand_fd = NULL;
379 return ECORE_CALLBACK_CANCEL;
380 }
381 if (ty->fd == -1)
382 {
383 ty->hand_fd = NULL;
384 return ECORE_CALLBACK_CANCEL;
385 }
386
387/* it seems the BSDs can not read from this side of the pair if the other side
388 * is closed */
389#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__)
390 if (ty->pid == -1)
391 {
392 ty->hand_fd = NULL;
393 return ECORE_CALLBACK_CANCEL;
394 }
395#endif
396
397 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
398 {
399 if (!_handle_read(ty, false_on_empty))
400 return ECORE_CALLBACK_CANCEL;
401 }
402
403 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
404 {
405 if (!_handle_write(ty))
406 return ECORE_CALLBACK_CANCEL;
407 }
408
409 return ECORE_CALLBACK_PASS_ON;
410}
411
412static Eina_Bool
413_cb_fd(void *data, Ecore_Fd_Handler *fd_handler)
414{
415 return _fd_do(data, fd_handler, EINA_FALSE);
366} 416}
367 417
368static Eina_Bool 418static Eina_Bool
@@ -386,7 +436,7 @@ _cb_exe_exit(void *data,
386 res = ECORE_CALLBACK_PASS_ON; 436 res = ECORE_CALLBACK_PASS_ON;
387 while (ty->hand_fd && res != ECORE_CALLBACK_CANCEL) 437 while (ty->hand_fd && res != ECORE_CALLBACK_CANCEL)
388 { 438 {
389 res = _fd_read_do(ty, ty->hand_fd, EINA_TRUE); 439 res = _fd_do(ty, ty->hand_fd, EINA_TRUE);
390 } 440 }
391 441
392 if (ty->hand_fd) ecore_main_fd_handler_del(ty->hand_fd); 442 if (ty->hand_fd) ecore_main_fd_handler_del(ty->hand_fd);
@@ -533,7 +583,7 @@ termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd,
533 ty->fd = STDIN_FILENO; 583 ty->fd = STDIN_FILENO;
534 ty->hand_fd = ecore_main_fd_handler_add(ty->fd, 584 ty->hand_fd = ecore_main_fd_handler_add(ty->fd,
535 ECORE_FD_READ | ECORE_FD_ERROR, 585 ECORE_FD_READ | ECORE_FD_ERROR,
536 _cb_fd_read, ty, 586 _cb_fd, ty,
537 NULL, NULL); 587 NULL, NULL);
538 _pty_size(ty); 588 _pty_size(ty);
539 termpty_save_register(ty); 589 termpty_save_register(ty);
@@ -747,10 +797,10 @@ termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd,
747 ty->slavefd = -1; 797 ty->slavefd = -1;
748 798
749 ty->hand_fd = ecore_main_fd_handler_add(ty->fd, ECORE_FD_READ, 799 ty->hand_fd = ecore_main_fd_handler_add(ty->fd, ECORE_FD_READ,
750 _cb_fd_read, ty, 800 _cb_fd, ty,
751 NULL, NULL); 801 NULL, NULL);
752 /* ensure we're not missing a read */ 802 /* ensure we're not missing a read */
753 _cb_fd_read(ty, ty->hand_fd); 803 _cb_fd(ty, ty->hand_fd);
754 804
755 _pty_size(ty); 805 _pty_size(ty);
756 termpty_save_register(ty); 806 termpty_save_register(ty);
@@ -846,6 +896,7 @@ termpty_free(Termpty *ty)
846 free(ty->hl.bitmap); 896 free(ty->hl.bitmap);
847 free(ty->buf); 897 free(ty->buf);
848 free(ty->tabs); 898 free(ty->tabs);
899 ty_sb_free(&ty->write_buffer);
849 free(ty); 900 free(ty);
850} 901}
851 902
@@ -1251,18 +1302,14 @@ termpty_cell_get(Termpty *ty, int y_requested, int x_requested)
1251void 1302void
1252termpty_write(Termpty *ty, const char *input, int len) 1303termpty_write(Termpty *ty, const char *input, int len)
1253{ 1304{
1254#if defined(ENABLE_TESTS)
1255 ty_sb_add(&ty->write_buffer, input, len);
1256#else
1257 int fd = ty->fd;
1258#if defined(ENABLE_FUZZING) 1305#if defined(ENABLE_FUZZING)
1259 return; 1306 return;
1260#endif 1307#endif
1261 if (fd < 0) return; 1308 ty_sb_add(&ty->write_buffer, input, len);
1262 if (write(fd, input, len) < 0) 1309 ecore_main_fd_handler_active_set(ty->hand_fd,
1263 ERR(_("Could not write to file descriptor %d: %s"), 1310 ECORE_FD_ERROR |
1264 fd, strerror(errno)); 1311 ECORE_FD_READ |
1265#endif 1312 ECORE_FD_WRITE);
1266} 1313}
1267 1314
1268struct screen_info 1315struct screen_info
diff --git a/src/bin/termpty.h b/src/bin/termpty.h
index b892051..a2a1efc 100644
--- a/src/bin/termpty.h
+++ b/src/bin/termpty.h
@@ -168,9 +168,7 @@ struct _Termpty
168 Backlog_Beacon backlog_beacon; 168 Backlog_Beacon backlog_beacon;
169 int w, h; 169 int w, h;
170 int fd, slavefd; 170 int fd, slavefd;
171#if defined(ENABLE_TESTS)
172 struct ty_sb write_buffer; 171 struct ty_sb write_buffer;
173#endif
174 struct { 172 struct {
175 int curid; 173 int curid;
176 Eina_Hash *blocks; 174 Eina_Hash *blocks;
diff --git a/src/bin/tyfuzz.c b/src/bin/tyfuzz.c
index 8272b4a..9901581 100644
--- a/src/bin/tyfuzz.c
+++ b/src/bin/tyfuzz.c
@@ -271,14 +271,6 @@ _termpty_init(Termpty *ty, Config *config)
271 ty->backlog_beacon.screen_y = 0; 271 ty->backlog_beacon.screen_y = 0;
272} 272}
273 273
274static void
275_termpty_shutdown(Termpty *ty)
276{
277#if defined(ENABLE_TESTS)
278 ty_sb_free(&ty->write_buffer);
279#endif
280}
281
282int 274int
283main(int argc EINA_UNUSED, char **argv EINA_UNUSED) 275main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
284{ 276{
@@ -377,8 +369,6 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
377 _tytest_checksum(&_ty); 369 _tytest_checksum(&_ty);
378#endif 370#endif
379 371
380 _termpty_shutdown(&_ty);
381
382#ifdef TYTEST 372#ifdef TYTEST
383 tytest_shutdown(); 373 tytest_shutdown();
384#endif 374#endif