git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: Abhijeet Sonar <abhijeet.nkt@gmail.com>,
	Karthik Nayak <karthik.188@gmail.com>,
	git@vger.kernel.org, Paul Millar <paul.millar@desy.de>,
	Phillip Wood <phillip.wood123@gmail.com>,
	Elijah Newren <newren@gmail.com>
Subject: Re: Re* [PATCH v5] describe: refresh the index when 'broken' flag is used
Date: Wed, 26 Jun 2024 16:34:15 -0400	[thread overview]
Message-ID: <20240626203415.GA441931@coredump.intra.peff.net> (raw)
In-Reply-To: <xmqq8qyrzgi5.fsf@gitster.g>

On Wed, Jun 26, 2024 at 11:49:22AM -0700, Junio C Hamano wrote:

> 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?

>  * 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

  reply	other threads:[~2024-06-26 20:34 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-25 13:35 [PATCH v3] describe: refresh the index when 'broken' flag is used Abhijeet Sonar
2024-06-25 15:59 ` Junio C Hamano
2024-06-25 16:05   ` Junio C Hamano
2024-06-26 11:16     ` Karthik Nayak
2024-06-26  6:11   ` Abhijeet Sonar
2024-06-26  6:37   ` [PATCH v4] " Abhijeet Sonar
2024-06-26  6:50     ` Abhijeet Sonar
2024-06-26  6:52   ` [PATCH v5] " Abhijeet Sonar
2024-06-26 11:30     ` Karthik Nayak
2024-06-26 12:06       ` Abhijeet Sonar
2024-06-26 15:34         ` Re* " Junio C Hamano
2024-06-26 16:17           ` Junio C Hamano
2024-06-26 17:29             ` Abhijeet Sonar
2024-06-26 17:35               ` Junio C Hamano
2024-06-26 17:45                 ` Junio C Hamano
2024-06-26 18:07                 ` Abhijeet Sonar
2024-06-26 18:49                   ` Junio C Hamano
2024-06-26 20:34                     ` Jeff King [this message]
2024-06-27  0:33                       ` Jeff King
2024-06-26 21:23                     ` Karthik Nayak
2024-06-26 14:59       ` Junio C Hamano
2024-06-26 18:31     ` Junio C Hamano
2024-06-26 19:08       ` [PATCH v7] " Abhijeet Sonar
2024-06-26 19:25         ` Abhijeet Sonar
2024-06-27  6:01           ` Abhijeet Sonar
2024-06-27 15:47           ` Junio C Hamano
2024-06-27 17:33             ` Abhijeet Sonar
2024-06-30 16:12             ` Karthik Nayak
2024-07-01 19:06               ` Junio C Hamano
2024-07-02 10:13                 ` Karthik Nayak
2024-07-03 18:17                   ` Junio C Hamano
2024-07-03 20:41                     ` Karthik Nayak

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

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

  git send-email \
    --in-reply-to=20240626203415.GA441931@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=abhijeet.nkt@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=karthik.188@gmail.com \
    --cc=newren@gmail.com \
    --cc=paul.millar@desy.de \
    --cc=phillip.wood123@gmail.com \
    /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.
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 NNTP newsgroup(s).