git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: "René Scharfe" <l.s.r@web.de>
Cc: Junio C Hamano <gitster@pobox.com>,
	git@vger.kernel.org,
	Johannes Schindelin <Johannes.Schindelin@gmx.de>
Subject: Re: [PATCH v2] pipe_command(): mark stdin descriptor as non-blocking
Date: Wed, 10 Aug 2022 15:53:20 -0400	[thread overview]
Message-ID: <YvQMsMv3EhiI/rTb@coredump.intra.peff.net> (raw)
In-Reply-To: <0e1b8066-3f67-cec6-675a-05d2cf54c119@web.de>

On Wed, Aug 10, 2022 at 07:39:34AM +0200, René Scharfe wrote:

> > So it's weird that you'd see EAGAIN in this instance. Either the
> > underlying write() is refusing to do a partial write (and just returning
> > an error with EAGAIN in the first place), or the poll emulation is wrong
> > (telling us the descriptor is ready for writing when it isn't).
> 
> You're right, Windows' write needs two corrections.  The helper below
> reports what happens when we feed a pipe with writes of different sizes.
> On Debian on WSL 2 (Windows Subsystem for Linux) it says:
> [...]

Thanks for digging into this further. What you found makes sense to me
and explains what we're seeing.

> The two corrections mentioned above together with the enable_nonblock()
> implementation for Windows (and the removal of "false") suffice to let
> t3701 pass when started directly, but it still hangs when running the
> whole test suite using prove.

Interesting. I wish there was an easy way for me to poke at this, too. I
tried installing the Git for Windows SDK under wine, but unsurprisingly
it did not get very far.

Possibly I could try connecting to a running CI instance, but the test
did not seem to fail there! (Plus I'd have to figure out how to do
that... ;) ).

> I don't have time to investigate right now, but I still don't
> understand how xwrite() can possibly work against a non-blocking pipe.
> It loops on EAGAIN, which is bad if the only way forward is to read
> from a different fd to allow the other process to drain the pipe
> buffer so that xwrite() can write again.  I suspect pump_io_round()
> must not use xwrite() and should instead handle EAGAIN by skipping to
> the next fd.

Right, it's susceptible to looping forever in such a case. _But_ a
blocking write is likewise susceptible to blocking forever. In either
case, we're relying on the reading side to pull some bytes out of the
pipe so we can make forward progress.

The key thing is that pump_io() is careful never to initiate a write()
unless poll() has just told us that the descriptor is ready for writing.

If something unexpected happens there (i.e., the descriptor is not
really ready), a blocking descriptor is going to be stuck. And with
xwrite(), we're similarly stuck (just looping instead of blocking).
Without xwrite(), a non-blocking one _could_ be better off, because that
EAGAIN would make it up to pump_io(). But what is it supposed to do? I
guess it could go back into its main loop and hope that whatever bug
caused the mismatch between poll() and write() goes away.

But even that would not have fixed the problem here on Windows. From my
understanding, mingw_write() in this case would never write _any_ bytes.
So we'd never make forward progress, and just loop writing 0 bytes and
returning EAGAIN over and over.

So I dunno. We could try to be a bit more defensive about non-blocking
descriptors by avoiding xwrite() in this instance, but it only helps for
a particular class of weird OS behavior/bugs. I'd prefer to see a real
case that it would help before moving in that direction.

-Peff

  reply	other threads:[~2022-08-10 19:53 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-02  4:13 [RFC/PATCH] pipe_command(): mark stdin descriptor as non-blocking Jeff King
2022-08-02 15:04 ` Junio C Hamano
2022-08-02 15:39 ` Jeff King
2022-08-02 16:16   ` Junio C Hamano
2022-08-03  3:53     ` [PATCH v2] " Jeff King
2022-08-03 16:45       ` René Scharfe
2022-08-03 17:20         ` Jeff King
2022-08-03 21:56           ` René Scharfe
2022-08-05 15:36             ` Jeff King
2022-08-05 21:13               ` René Scharfe
2022-08-07 10:15                 ` René Scharfe
2022-08-07 17:41                   ` Jeff King
2022-08-10  5:39                     ` René Scharfe
2022-08-10 19:53                       ` Jeff King [this message]
2022-08-10 22:35                         ` René Scharfe
2022-08-11  8:52                           ` Jeff King
2022-08-10  5:39                     ` [PATCH] mingw: handle writes to non-blocking pipe René Scharfe
2022-08-10  9:07                       ` Johannes Schindelin
2022-08-10 20:02                       ` Jeff King
2022-08-10 22:34                         ` René Scharfe
2022-08-11  8:47                           ` Jeff King
2022-08-11 17:35                             ` René Scharfe
2022-08-11 18:20                               ` Jeff King
2022-08-14 15:37                                 ` René Scharfe
2022-08-17  5:39                                   ` Jeff King
2022-08-17  6:04                                     ` [PATCH v2 0/6] fix pipe_command() deadlock Jeff King
2022-08-17  6:04                                       ` [PATCH v2 1/6] compat: add function to enable nonblocking pipes Jeff King
2022-08-17 20:23                                         ` Junio C Hamano
2022-08-18  5:41                                           ` Jeff King
2022-08-17  6:05                                       ` [PATCH v2 2/6] nonblock: support Windows Jeff King
2022-08-17  6:06                                       ` [PATCH v2 3/6] git-compat-util: make MAX_IO_SIZE define globally available Jeff King
2022-08-17  6:08                                       ` [PATCH v2 4/6] pipe_command(): avoid xwrite() for writing to pipe Jeff King
2022-08-17  6:09                                       ` [PATCH v2 5/6] pipe_command(): handle ENOSPC when writing to a pipe Jeff King
2022-08-17 18:57                                         ` Junio C Hamano
2022-08-18  5:38                                           ` Jeff King
2022-08-17  6:10                                       ` [PATCH v2 6/6] pipe_command(): mark stdin descriptor as non-blocking Jeff King
2022-08-17  6:20                                       ` [PATCH v2 0/6] fix pipe_command() deadlock Jeff King
2022-08-19 21:19                                       ` René Scharfe
2022-08-20  7:04                                         ` Jeff King
2022-08-07 10:14               ` [PATCH v2] pipe_command(): mark stdin descriptor as non-blocking René Scharfe
2022-08-08 12:55                 ` Johannes Schindelin
2022-08-08 12:59       ` Johannes Schindelin
2022-08-09 13:04         ` Jeff King
2022-08-09 22:10           ` Johannes Schindelin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YvQMsMv3EhiI/rTb@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=l.s.r@web.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).