Skip to content
  • Johannes Schindelin's avatar
    vreportf(): avoid relying on stdio buffering · 116d1fa6
    Johannes Schindelin authored and Junio C Hamano's avatar Junio C Hamano committed
    The MSVC runtime behavior differs from glibc's with respect to
    `fprintf(stderr, ...)` in that the former writes out the message
    character by character.
    
    In t5516, this leads to a funny problem where a `git fetch` process as
    well as the `git upload-pack` process spawned by it _both_ call `die()`
    at the same time. The output can look like this:
    
    	fatal: git uploadfata-lp: raemcokte :error:  upload-pnot our arcef k6: n4ot our ea4cr1e3f 36d45ea94fca1398e86a771eda009872d63adb28598f6a9
    	8e86a771eda009872d6ab2886
    
    Let's avoid this predicament altogether by rendering the entire message,
    including the prefix and the trailing newline, into the buffer we
    already have (and which is still fixed size) and then write it out via
    `write_in_full()`.
    
    We still clip the message to at most 4095 characters.
    
    The history of `vreportf()` with regard to this issue includes the
    following commits:
    
    d048a96e (2007-11-09) - 'char msg[256]' is introduced to avoid interleaving
    389d1767 (2009-03-25) - Buffer size increased to 1024 to avoid truncation
    625a860c (2009-11-22) - Buffer size increased to 4096 to avoid truncation
    f4c3edc0 (2015-08-11) - Buffer removed to avoid truncation
    b5a9e435 (2017-01-11) - Reverts f4c3edc0 to be able to replace control
                            chars before sending to stderr
    9ac13ec9 (2006-10-11) - Another attempt to solve interleaving.
                            This is seemingly related to d048a96e.
    137a0d0e (2007-11-19) - Addresses out-of-order for display()
    34df8aba (2009-03-10) - Switches xwrite() to fprintf() in recv_sideband()
                            to support UTF-8 emulation
    eac14f89 (2012-01-14) - Removes the need for fprintf() for UTF-8 emulation,
                            so it's safe to use xwrite() again
    5e5be9e2
    
     (2016-06-28) - recv_sideband() uses xwrite() again
    
    Note that we print nothing if the `vsnprintf()` call failed to render
    the error message; There is little we can do in that case, and it should
    not happen anyway.
    
    The process may have written to `stderr` and there may be something left
    in the buffer kept in the stdio layer. Call `fflush(stderr)` before
    writing the message we prepare in this function.
    
    Helped-by: default avatarJeff King <peff@peff.net>
    Helped-by: default avatarAlexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com>
    Helped-by: default avatarSZEDER Gábor <szeder.dev@gmail.com>
    Helped-by: default avatarJunio C Hamano <gitster@pobox.com>
    Signed-off-by: default avatarJohannes Schindelin <johannes.schindelin@gmx.de>
    Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
    116d1fa6