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

Re: Re* [PATCH v5] describe: refresh the index when 'broken' flag is used

From
Jeff King <peff@peff.net>
Date
Jun 26, 2024, 20:34 UTC
Message-ID
<20240626203415.GA441931@coredump.intra.peff.net>
In-Reply-To
<xmqq8qyrzgi5.fsf@gitster.g>
On Wed, Jun 26, 2024 at 11:49:22AM -0700, Junio C Hamano wrote:
Show 29 quoted lines
> Abhijeet Sonar <abhijeet.nkt@gmail.com> writes:
> 
> > On 26/06/24 23:05, Junio C Hamano wrote:
> >> Abhijeet Sonar <abhijeet.nkt@gmail.com> writes:
> >> 
> >>> To me, this looks much better.  child_process_clear's name already
> >>> suggests that is sort of like a destructor, so it makes sense to
> >>> re-initialize everything here.  I even wonder why it was not that way to
> >>> begin with.  I suppose no callers are assuming that it only clears args
> >>> and env though?
> >> 
> >> I guess that validating that supposition is a prerequisite to
> >> declare the change as "much better" and "makes sense".
> >
> > OK.  I found one: at the end of submodule.c:push_submodule()
> >
> > 	if (...) {
> > 		...some setup...
> > 		if (run_command(&cp))
> > 			return 0;
> > 		close(cp.out);
> > 	}
> 
> This is curious.
> 
>  * What is this thing trying to do?  When run_command() fails, it
>    wants to leave cp.out open, so that the caller this returns to
>    can write into it???  That cannot be the case, as cp itself is
>    internal.  So does this "close(cp.out)" really matter?

I think it's totally broken. Using cp.out, cp.in, etc, with run_command() is a deadlock waiting to happen, since it implies opening a pipe, not doing anything with our end, and then doing a waitpid() on the child.

You'd always want to use start_command(), and then do something useful with the pipe, and then finish_command(). Arguably run_command() should bug if cp.out, etc are non-zero.

In this case the code leaves cp.out as 0, so we are not asking for a pipe. That is good, and we are not subject to any race/deadlock. But then...what is the cleanup trying to do? This will always just close(0), the parent's stdin. That is certainly surprising, but I guess nobody ever noticed because git-push does not usually read from its stdin.

So I think the close() is superfluous and should be deleted. It goes all the way back to eb21c732d6 (push: teach --recurse-submodules the on-demand option, 2012-03-29). I guess at one point the author thought we'd read output from a pipe (rather than letting it just go to the parent's stdout) and this was leftover?

Show 7 quoted lines
>  * Even though we are running child_process_clear() to release the
>    resources in run_command() we are not closing the file descriptor
>    cp.out in the child_process_clear() and force the caller to close
>    it instead.  An open file descriptor is a resource, and a file
>    descriptor opened but forgotten is considered a leak.  I wonder
>    if child_process_clear() should be closing the file descriptor,
>    at least the ones it opened or dup2()ed.

Usually the caller will have handled this already (since it cares about exactly _when_ to close), so we'd end up double-closing in most cases. This is sometimes harmless (you'll get EBADF), but is a problem if the descriptor was assigned to something else in the meantime.

In most cases callers shouldn't be using child_process_clear() at all after start_command(), etc. Either:

  - start_command() failed, in which case it cleans up everything
    already (both in the struct and any pipes it opened)
  - we succeeded in starting the command, in which case
    child_process_clear() is insufficient. You need to actually
    finish_command() to avoid leaking the pid.
  - after finish_command(), the struct has been cleaned already. You do
    need to close pipes in the caller, but you'd have to do so before
    calling finish_command() anyway, to avoid the deadlock.

You really only need to call child_process_clear() yourself when you set up a struct but didn't actually start the process. And from a quick skim over the grep results, it looks like that's how it's used.

-Peff
Previous: Junio C HamanoNext: Jeff King
Message 18 of 32 in “describe: refresh the index when 'broken' flag is used”
  1. describe: refresh the index when 'broken' flag is usedAbhijeet Sonar, Jun 25, 2024
  2. Junio C HamanoJun 25, 2024
  3. Junio C HamanoJun 25, 2024
  4. Karthik NayakJun 26, 2024
  5. Abhijeet SonarJun 26, 2024
  6. describe: refresh the index when 'broken' flag is usedAbhijeet Sonar, Jun 26, 2024
  7. Abhijeet SonarJun 26, 2024
  8. describe: refresh the index when 'broken' flag is usedAbhijeet Sonar, Jun 26, 2024
  9. Karthik NayakJun 26, 2024
  10. Abhijeet SonarJun 26, 2024
  11. Re* [PATCH v5] describe: refresh the index when 'broken' flag is usedJunio C Hamano, Jun 26, 2024
  12. Junio C HamanoJun 26, 2024
  13. Abhijeet SonarJun 26, 2024
  14. Junio C HamanoJun 26, 2024
  15. Junio C HamanoJun 26, 2024
  16. Abhijeet SonarJun 26, 2024
  17. Junio C HamanoJun 26, 2024
  18. Jeff KingJun 26, 2024
  19. Jeff KingJun 27, 2024
  20. Karthik NayakJun 26, 2024
  21. Junio C HamanoJun 26, 2024
  22. Junio C HamanoJun 26, 2024
  23. describe: refresh the index when 'broken' flag is usedAbhijeet Sonar, Jun 26, 2024
  24. Abhijeet SonarJun 26, 2024
  25. Abhijeet SonarJun 27, 2024
  26. Junio C HamanoJun 27, 2024
  27. Abhijeet SonarJun 27, 2024
  28. Karthik NayakJun 30, 2024
  29. Junio C HamanoJul 1, 2024
  30. Karthik NayakJul 2, 2024
  31. Junio C HamanoJul 3, 2024
  32. Karthik NayakJul 3, 2024

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.