Ticket #3983: fix_the_sometimes_truncated_shell_output_in_mc.patch

File fix_the_sometimes_truncated_shell_output_in_mc.patch, 3.8 KB (added by howaboutsynergy, 5 years ago)
  • src/subshell/common.c

    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) 
    464464    int i;                      /* Loop counter */ 
    465465 
    466466    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; 
    473468 
    474469    while (TRUE) 
    475470    { 
    476471        int maxfdp; 
    477472 
     473        wtime.tv_sec = (fail_on_error && !gotpwdoutput) ? 10:0; 
     474        wtime.tv_usec = 10000; 
     475 
    478476        if (!subshell_alive) 
    479477            return FALSE; 
    480478 
    feed_subshell (int how, gboolean fail_on_error) 
    540538            maxfdp = MAX (maxfdp, STDIN_FILENO); 
    541539        } 
    542540 
    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) 
    544542        { 
    545543            /* Despite using SA_RESTART, we still have to check for this */ 
    546544            if (errno == EINTR) 
    feed_subshell (int how, int fail_on_error) 
    508506 
    509507        if (FD_ISSET (mc_global.tty.subshell_pty, &read_set)) 
    510508            /* 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 */ 
    516509        { 
    517510            bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer)); 
    518511 
    feed_subshell (int how, int fail_on_error) 
    545538 
    546539            subshell_cwd[bytes - 1] = 0;        /* Squash the final '\n' */ 
    547540 
    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; 
    556542        } 
    557543 
    558544        else if (FD_ISSET (STDIN_FILENO, &read_set)) 
    feed_subshell (int how, int fail_on_error) 
    581567            if (pty_buffer[bytes - 1] == '\n' || pty_buffer[bytes - 1] == '\r') 
    582568                subshell_ready = FALSE; 
    583569        } 
    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; 
    586595    } 
     596    return TRUE; 
    587597} 
    588598 
    589599/* --------------------------------------------------------------------------------------------- */