This patch is to fix an issue in mc (midnight commander)
whereby sometimes the subshell output was truncated and if small enough
completely discarded.
The fix handles the case when the order of two different inputs
(shell output and the pwd from PROMPT_COMMAND) don't arrive in that order.
This happens sometimes and this is when the truncation was in effect.
Also note that shell being STOP-ped can also happen in any order with the above two.
reported issue: https://github.com/MidnightCommander/mc/issues/44#issuecomment-60467020
UPdate: subshell.c location changed with commit: 974ab368ec30fcd68e595252668d1542a5352619
diff --git a/src/subshell.c b/src/subshell.c
index a85b258..f722396 100644
a
|
b
|
feed_subshell (int how, int fail_on_error) |
464 | 464 | int i; /* Loop counter */ |
465 | 465 | |
466 | 466 | struct timeval wtime; /* Maximum time we wait for the subshell */ |
467 | | struct timeval *wptr; |
468 | | |
469 | | /* we wait up to 10 seconds if fail_on_error, forever otherwise */ |
470 | | wtime.tv_sec = 10; |
471 | | wtime.tv_usec = 0; |
472 | | wptr = fail_on_error ? &wtime : NULL; |
| 467 | int gotpwdoutput=FALSE; |
473 | 468 | |
474 | 469 | while (TRUE) |
475 | 470 | { |
476 | 471 | int maxfdp; |
477 | 472 | |
| 473 | wtime.tv_sec = (fail_on_error && !gotpwdoutput) ? 10:0; |
| 474 | wtime.tv_usec = 10000; |
| 475 | |
478 | 476 | if (!subshell_alive) |
479 | 477 | return FALSE; |
480 | 478 | |
… |
… |
feed_subshell (int how, gboolean fail_on_error) |
540 | 538 | maxfdp = MAX (maxfdp, STDIN_FILENO); |
541 | 539 | } |
542 | 540 | |
543 | | if (select (maxfdp + 1, &read_set, NULL, NULL, wptr) == -1) |
| 541 | if (select (maxfdp + 1, &read_set, NULL, NULL, ( (ACTIVE == subshell_state && subshell_ready) ? NULL : &wtime) ) == -1) |
544 | 542 | { |
545 | 543 | /* Despite using SA_RESTART, we still have to check for this */ |
546 | 544 | if (errno == EINTR) |
… |
… |
feed_subshell (int how, int fail_on_error) |
508 | 506 | |
509 | 507 | if (FD_ISSET (mc_global.tty.subshell_pty, &read_set)) |
510 | 508 | /* Read from the subshell, write to stdout */ |
511 | | |
512 | | /* This loop improves performance by reducing context switches |
513 | | by a factor of 20 or so... unfortunately, it also hangs MC |
514 | | randomly, because of an apparent Linux bug. Investigate. */ |
515 | | /* for (i=0; i<5; ++i) * FIXME -- experimental */ |
516 | 509 | { |
517 | 510 | bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer)); |
518 | 511 | |
… |
… |
feed_subshell (int how, int fail_on_error) |
545 | 538 | |
546 | 539 | subshell_cwd[bytes - 1] = 0; /* Squash the final '\n' */ |
547 | 540 | |
548 | | synchronize (); |
549 | | |
550 | | subshell_ready = TRUE; |
551 | | if (subshell_state == RUNNING_COMMAND) |
552 | | { |
553 | | subshell_state = INACTIVE; |
554 | | return TRUE; |
555 | | } |
| 541 | gotpwdoutput=TRUE; |
556 | 542 | } |
557 | 543 | |
558 | 544 | else if (FD_ISSET (STDIN_FILENO, &read_set)) |
… |
… |
feed_subshell (int how, int fail_on_error) |
581 | 567 | if (pty_buffer[bytes - 1] == '\n' || pty_buffer[bytes - 1] == '\r') |
582 | 568 | subshell_ready = FALSE; |
583 | 569 | } |
584 | | else |
585 | | return FALSE; |
| 570 | else { |
| 571 | if (fail_on_error) { |
| 572 | if (subshell_stopped && gotpwdoutput && subshell_state==RUNNING_COMMAND) { |
| 573 | break; |
| 574 | }else{ |
| 575 | return FALSE; |
| 576 | } |
| 577 | }else { |
| 578 | if (subshell_stopped) { |
| 579 | if (subshell_state == ACTIVE) { |
| 580 | synchronize (); |
| 581 | subshell_ready = TRUE; |
| 582 | } else { |
| 583 | break; |
| 584 | } |
| 585 | } |
| 586 | } |
| 587 | } |
| 588 | } |
| 589 | |
| 590 | synchronize (); |
| 591 | subshell_ready = TRUE; |
| 592 | if (subshell_state == RUNNING_COMMAND) |
| 593 | { |
| 594 | subshell_state = INACTIVE; |
586 | 595 | } |
| 596 | return TRUE; |
587 | 597 | } |
588 | 598 | |
589 | 599 | /* --------------------------------------------------------------------------------------------- */ |