git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 1/1] vreportf(): avoid buffered write in favor of unbuffered one

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Oct 29, 2019, 12:30 UTC
Message-ID
<nycvar.QRO.7.76.6.1910291222500.46@tvgsbejvaqbjf.bet>
In-Reply-To
<xmqqeeyw6xyr.fsf@gitster-ct.c.googlers.com>
Hi Junio,
On Tue, 29 Oct 2019, Junio C Hamano wrote:
Show 8 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > Also please note that we `fflush(stderr)` here to help when running in a
> > Git Bash on Windows: in this case, `stderr` is not actually truly
> > unbuffered, and needs the extra help.
>
> Yuck.  So on all systems, vreportf() now totally bypasses stdio?
Yep ;-)
Show 5 quoted lines
> Also, this is only to help output from us that goes via vreportf() and
> other codepaths in us that use stdio to write to the standard error
> stream can still get mixed on Windows (I think the answer is yes,
> because we wouldn't need fflush() in this patch if we are covering all
> writes to the standard error stream)?

Yes, `write()` can get interrupted, so there is still a slight chance of interleaving.

However, with `fprintf()`, apparently the MSVC runtime essentially writes and flushes one character at a time, which will make it _much_ more likely that two competing processes write interleaved messages to `stderr`.

Show 8 quoted lines
> By the way, I'd retitle the patch to highlight that we are still doing
> buffered write, if I were doing this topic.  We are just avoiding some
> implementations of stdio that do not give us buffering and doing the
> buffering ourselves.
>
>     Subject: vreportf(): don't rely on stdio buffering
>
> or something like that.
Good idea.
Show 21 quoted lines
> > Co-authored-by: Alexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com>
> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> > ---
> >  usage.c | 12 +++++++++---
> >  1 file changed, 9 insertions(+), 3 deletions(-)
> >
> > diff --git a/usage.c b/usage.c
> > index 2fdb20086b..4328894dce 100644
> > --- a/usage.c
> > +++ b/usage.c
> > @@ -10,13 +10,19 @@ void vreportf(const char *prefix, const char *err, va_list params)
> >  {
> >  	char msg[4096];
> >  	char *p;
> > -
> > -	vsnprintf(msg, sizeof(msg), err, params);
> > +	size_t off = strlcpy(msg, prefix, sizeof(msg));
>
> Like snprintf(3) the strlcpy() and strlcat() functions return the
> total length of the string they tried to create.  For strlcpy() that
> means the length of src.

True (I misread `compat/strlcpy.c` and forgot to consult the documentation). This length can be longer than `msg`, of course.

> So "off" would be strlen(prefix), which could be longer than
> sizeof(msg)?  Then what happens to this vsnprintf() we see below?
A problem.

I `git grep`ed and saw that only very short `prefix`es are hard-coded. So that is a hypothetical concern.

However, Alex also indicated his discomfort with this, so I will change the code to account for a `prefix` that is too long (the entire error message will be clipped away in that case, which is unfortunate, but to be expected).

Show 12 quoted lines
> > +	int ret = vsnprintf(msg + off, sizeof(msg) - off, err, params);
> >  	for (p = msg; *p; p++) {
> >  		if (iscntrl(*p) && *p != '\t' && *p != '\n')
> >  			*p = '?';
> >  	}
> > -	fprintf(stderr, "%s%s\n", prefix, msg);
>
> Strictly speaking this is a breaking change in that control
> sequences in prefix are now clobbered.  Does any caller call this
> function with prefix like "^M\033[K<some string>" to overwrite the
> last output line with the new message?  If not, then probably we do
> not have to worry about it (and reusing msg[] does feel attractive).

Such a sequence would not exactly be a prefix, but okay, I changed the code to replace only characters in the non-prefix part. For good measure, I also detect `NUL`s in that part and shorten `ret` in that case (think `die("This was an\0unintentional NUL")`).

Thanks for the review! Dscho

Show 11 quoted lines
> > +	if (ret > 0) {
> > +		if (off + ret > sizeof(msg) - 1)
> > +			ret = sizeof(msg) - 1 - off;
> > +		msg[off + ret] = '\n'; /* we no longer need a NUL */
> > +		fflush(stderr);
> > +		xwrite(2, msg, off + ret + 1);
> > +	}
> >  }
> >
> >  static NORETURN void usage_builtin(const char *err, va_list params)
>
Previous: Junio C HamanoNext: Jeff King
Message 4 of 34 in “Fix t5516 flakiness in Visual Studio builds”
  1. 0/1 Fix t5516 flakiness in Visual Studio buildsJohannes Schindelin via GitGitGadget, Oct 28, 2019
  2. 1/1 vreportf(): avoid buffered write in favor of unbuffered oneJohannes Schindelin via GitGitGadget, Oct 28, 2019
  3. Junio C HamanoOct 29, 2019
  4. Johannes SchindelinOct 29, 2019
  5. Jeff KingOct 29, 2019
  6. Johannes SchindelinOct 29, 2019
  7. Jeff KingOct 29, 2019
  8. Johannes SchindelinOct 29, 2019
  9. Junio C HamanoOct 30, 2019
  10. Junio C HamanoOct 29, 2019
  11. SZEDER GáborOct 29, 2019
  12. Johannes SchindelinOct 29, 2019
  13. Jeff KingOct 29, 2019
  14. Johannes SchindelinOct 29, 2019
  15. 0/1 Fix t5516 flakiness in Visual Studio buildsJohannes Schindelin via GitGitGadget, Oct 29, 2019
  16. 1/1 vreportf(): avoid relying on stdio bufferingJohannes Schindelin via GitGitGadget, Oct 29, 2019
  17. Alexandr MiloslavskiyOct 29, 2019
  18. Johannes SchindelinOct 29, 2019
  19. Jeff KingOct 29, 2019
  20. Alexandr MiloslavskiyOct 29, 2019
  21. Alexandr MiloslavskiyOct 29, 2019
  22. 0/1 Fix t5516 flakiness in Visual Studio buildsJohannes Schindelin via GitGitGadget, Oct 29, 2019
  23. 1/1 vreportf(): avoid relying on stdio bufferingJohannes Schindelin via GitGitGadget, Oct 29, 2019
  24. Jeff KingOct 29, 2019
  25. Johannes SchindelinOct 30, 2019
  26. Jeff KingOct 31, 2019
  27. Johannes SchindelinOct 31, 2019
  28. Jeff KingOct 31, 2019
  29. Johannes SchindelinNov 1, 2019
  30. Junio C HamanoOct 30, 2019
  31. Johannes SchindelinOct 30, 2019
  32. 0/1 Fix t5516 flakiness in Visual Studio buildsJohannes Schindelin via GitGitGadget, Oct 30, 2019
  33. 1/1 vreportf(): avoid relying on stdio bufferingJohannes Schindelin via GitGitGadget, Oct 30, 2019
  34. Junio C HamanoNov 2, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.