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

Re: Closing fds twice when using remote helpers

From
Jeff King <peff@peff.net>
Date
May 16, 2019, 03:28 UTC
Message-ID
<20190516032802.GB4596@sigill.intra.peff.net>
In-Reply-To
<20190516004802.fmtdz52xxcplkgcf@glandium.org>
On Thu, May 16, 2019 at 09:48:02AM +0900, Mike Hommey wrote:
Show 23 quoted lines
> > diff --git a/transport-helper.c b/transport-helper.c
> > index fcd2a58d0e..45cdf891ec 100644
> > --- a/transport-helper.c
> > +++ b/transport-helper.c
> > @@ -433,7 +433,7 @@ static int get_importer(struct transport *transport, struct child_process *fasti
> >  	struct helper_data *data = transport->data;
> >  	int cat_blob_fd, code;
> >  	child_process_init(fastimport);
> > -	fastimport->in = helper->out;
> > +	fastimport->in = xdup(helper->out);
> >  	argv_array_push(&fastimport->args, "fast-import");
> >  	argv_array_push(&fastimport->args, debug ? "--stats" : "--quiet");
> >  
> > 
> > One thing I'd wonder, though: what is the contract between the helper
> > and fast-import here? In the current code, when the helper closes its
> > stdout, fast-import will see EOF. But not if we are holding on to
> > another copy of the descriptor.
> 
> The helper is supposed to finish the fast-import stream with "done".
> The documentation doesn't say much, but it also seems like the helper
> could theoretically continue to respond to commands it's sent after
> having done so, but that currently never happens AFAICT.

Hmm. We do not even pass --done to fast-import. If we are really expecting everybody to say "done", then it seems like we ought to be doing so. I think that "done" came much later than the concept of fast-import, so while most reasonable importers would send it, I suspect antique ones would not.

So I was all ready to say that we need to do it the other way (pass off ownership) in order for fast-import to exit when the helper closes the descriptor. But actually, I think I am being silly. The duplicated descriptor is the _output_ from the helper, not the _input_ to fast-import. So if we are also holding that output descriptor, fast-import will not care. It is only the helper which would then not notice fast-import dying (and continue writing to the descriptor without EPIPE, since we are still on the other end of it).

I think that's probably OK, as we would see fast-import exit and then continue ourselves. We'd probably die() immediately assuming fast-import exits with an error. But if we don't, want happens? The helper would eventually block if it fills the pipe buffer. We'd eventually end up in disconnect_helper(). I think it would work out because we close(data->helper->out) before trying to reap the child, so it would get SIGPIPE then and exit.

So I think that works. But I have to admit that handing off ownership seems simpler to reason about. :)

Totally orthogonal, but I think we might also want to introduce a helper capability so that import helpers can say "I always send 'done' to fast-import". And then we can pass "--done" to fast-import, which means it would detect a truncated stream.

-Peff
Previous: Mike HommeyNext: Mike Hommey
Message 7 of 10 in “Closing fds twice when using remote helpers”
  1. Mike HommeyMay 15, 2019
  2. Ævar Arnfjörð BjarmasonMay 15, 2019
  3. Johannes SixtMay 15, 2019
  4. Mike HommeyMay 15, 2019
  5. Jeff KingMay 15, 2019
  6. Mike HommeyMay 16, 2019
  7. Jeff KingMay 16, 2019
  8. Mike HommeyMay 16, 2019
  9. Jeff KingMay 16, 2019
  10. Mike HommeyMay 16, 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.