git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] Report remote helper exec failures
@ 2009-12-24 17:49 Ilari Liusvaara
  2009-12-24 17:49 ` [RFC PATCH 1/2] Report exec errors from run-command Ilari Liusvaara
  2009-12-24 17:49 ` [RFC PATCH 2/2] Improve transport helper exec failure reporting Ilari Liusvaara
  0 siblings, 2 replies; 11+ messages in thread
From: Ilari Liusvaara @ 2009-12-24 17:49 UTC (permalink / raw)
  To: git

Actually give useful error messages if executing git remote helper fails
for some reason.

The previous error message was:

git: 'remote-fail' is not a git-command. See 'git --help'

This changes the error message to:

'Unable to find remote helper for "nonexistent"'

or

'Unable to run helper HelperThatGetsEACCESS: Permission denied' 
(or whatever the errno is).


Patch series is based on v1.6.6.

One of the changes is adjacent to changes in external helper dispatch
support change and gets merge conflict. Here's how I resolved that
conflict for testing:

        helper->argv[2] = remove_ext_force(transport->url);
        helper->git_cmd = 0;
        if (start_command(helper)) {
                if (errno == ENOENT)
                        die("Unable to find remote helper for \"%s\"",
                                data->name);
                else
                        die("Unable to run helper %s: %s", helper->argv[0],
                                strerror(errno));
        }

The first line in that comes from dispatch support and the rest come from
exec failure reporting.


Ilari Liusvaara (2):
  Report exec errors from run-command
  Improve transport helper exec failure reporting

 run-command.c      |   72 +++++++++++++++++++++++++++++++++++++++++++++++++--
 transport-helper.c |   14 +++++++---
 2 files changed, 79 insertions(+), 7 deletions(-)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RFC PATCH 1/2] Report exec errors from run-command
  2009-12-24 17:49 [RFC PATCH 0/2] Report remote helper exec failures Ilari Liusvaara
@ 2009-12-24 17:49 ` Ilari Liusvaara
  2009-12-25  7:35   ` Junio C Hamano
  2009-12-25 14:39   ` Johannes Sixt
  2009-12-24 17:49 ` [RFC PATCH 2/2] Improve transport helper exec failure reporting Ilari Liusvaara
  1 sibling, 2 replies; 11+ messages in thread
From: Ilari Liusvaara @ 2009-12-24 17:49 UTC (permalink / raw)
  To: git

Previously run-command was unable to report errors happening in exec
call. Change it to pass errno from failed exec to errno value at
return.

The errno value passing can be done by opening close-on-exec pipe and
piping the error code through in case of failure. In case of success,
close-on-exec closes the pipe on successful exec and parent process
gets end of file on read.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 run-command.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/run-command.c b/run-command.c
index cf2d8f7..d334d0f 100644
--- a/run-command.c
+++ b/run-command.c
@@ -76,9 +76,60 @@ fail_pipe:
 	trace_argv_printf(cmd->argv, "trace: run_command:");
 
 #ifndef WIN32
+{
+	int report_pipe[2] = {-1, -1};
+
+	if (pipe(report_pipe) < 0)
+		warning("Can't open pipe for exec status report: %s\n",
+			strerror(errno));
+
 	fflush(NULL);
 	cmd->pid = fork();
-	if (!cmd->pid) {
+	if (cmd->pid > 0) {
+		int r = 0, ret;
+		while(close(report_pipe[1]) < 0 && errno != EBADF);
+read_again:
+		if (report_pipe[0] > 0)
+			r = read(report_pipe[0], &ret, sizeof(ret));
+		if (r < 0 && (errno == EAGAIN || errno == EINTR ||
+			errno == EWOULDBLOCK))
+			goto read_again;
+		else if (r < 0)
+			warning("Can't read exec status report: %s\n",
+				strerror(errno));
+		else if (r == 0)
+			;
+		else if (r < sizeof(ret))
+			warning("Received incomplete exec status report.\n");
+		else {
+			failed_errno = ret;
+			/*
+			 * Clean up the process that did the failed execution
+			 * so no zombies remain.
+			 */
+wait_again:
+			r = waitpid(cmd->pid, &ret, 0);
+			if (r < 0 && errno != ECHILD)
+				goto wait_again;
+			cmd->pid = -1;
+		}
+	} else if (!cmd->pid) {
+		int r = 0;
+		int flags;
+		while(close(report_pipe[0]) < 0 && errno != EBADF);
+
+		flags = fcntl(report_pipe[1], F_GETFD);
+		if (flags < 0)
+			r = -1;
+		flags |= FD_CLOEXEC;
+		r = (r || fcntl(report_pipe[1], F_SETFD, flags));
+		if (r) {
+			warning("Can't FD_CLOEXEC pipe for exec status "
+				"report: %s\n", strerror(errno));
+			while(close(report_pipe[1]) < 0 && errno != EBADF);
+			report_pipe[1] = -1;
+		}
+
 		if (cmd->no_stdin)
 			dup_devnull(0);
 		else if (need_in) {
@@ -126,13 +177,28 @@ fail_pipe:
 		} else {
 			execvp(cmd->argv[0], (char *const*) cmd->argv);
 		}
+		failed_errno = errno;
+
 		trace_printf("trace: exec '%s' failed: %s\n", cmd->argv[0],
 				strerror(errno));
+
+		r = 0;
+write_again:
+		if (report_pipe[1] >= 0)
+			r = write(report_pipe[1], &failed_errno,
+				sizeof(failed_errno));
+		if (r < 0 && (errno == EAGAIN || errno == EINTR ||
+			errno == EWOULDBLOCK))
+			goto write_again;
+		else if (r < 0)
+			warning("Can't write exec status report: %s\n",
+				strerror(errno));
+
 		exit(127);
-	}
-	if (cmd->pid < 0)
+	} else if (cmd->pid < 0)
 		error("cannot fork() for %s: %s", cmd->argv[0],
 			strerror(failed_errno = errno));
+}
 #else
 {
 	int s0 = -1, s1 = -1, s2 = -1;	/* backups of stdin, stdout, stderr */
-- 
1.6.6.3.gaa2e1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH 2/2] Improve transport helper exec failure reporting
  2009-12-24 17:49 [RFC PATCH 0/2] Report remote helper exec failures Ilari Liusvaara
  2009-12-24 17:49 ` [RFC PATCH 1/2] Report exec errors from run-command Ilari Liusvaara
@ 2009-12-24 17:49 ` Ilari Liusvaara
  2009-12-25  7:44   ` Junio C Hamano
  1 sibling, 1 reply; 11+ messages in thread
From: Ilari Liusvaara @ 2009-12-24 17:49 UTC (permalink / raw)
  To: git

Previously transport-helper exec failure error reporting was pretty
much useless as it didn't report errors from execve, only from pipe
and fork. Now that run-command passes errno from exec, use the
improved support to actually print useful errors if execution fails.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 transport-helper.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/transport-helper.c b/transport-helper.c
index 5078c71..0965c9b 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -31,13 +31,19 @@ static struct child_process *get_helper(struct transport *transport)
 	helper->out = -1;
 	helper->err = 0;
 	helper->argv = xcalloc(4, sizeof(*helper->argv));
-	strbuf_addf(&buf, "remote-%s", data->name);
+	strbuf_addf(&buf, "git-remote-%s", data->name);
 	helper->argv[0] = strbuf_detach(&buf, NULL);
 	helper->argv[1] = transport->remote->name;
 	helper->argv[2] = transport->url;
-	helper->git_cmd = 1;
-	if (start_command(helper))
-		die("Unable to run helper: git %s", helper->argv[0]);
+	helper->git_cmd = 0;
+	if (start_command(helper)) {
+		if (errno == ENOENT)
+			die("Unable to find remote helper for \"%s\"",
+				data->name);
+		else
+			die("Unable to run helper %s: %s", helper->argv[0],
+				strerror(errno));
+	}
 	data->helper = helper;
 
 	write_str_in_full(helper->in, "capabilities\n");
-- 
1.6.6.3.gaa2e1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/2] Report exec errors from run-command
  2009-12-24 17:49 ` [RFC PATCH 1/2] Report exec errors from run-command Ilari Liusvaara
@ 2009-12-25  7:35   ` Junio C Hamano
  2009-12-25  7:46     ` Junio C Hamano
                       ` (2 more replies)
  2009-12-25 14:39   ` Johannes Sixt
  1 sibling, 3 replies; 11+ messages in thread
From: Junio C Hamano @ 2009-12-25  7:35 UTC (permalink / raw)
  To: Ilari Liusvaara; +Cc: git

Ilari Liusvaara <ilari.liusvaara@elisanet.fi> writes:

> Previously run-command was unable to report errors happening in exec
> call. Change it to pass errno from failed exec to errno value at
> return.
>
> The errno value passing can be done by opening close-on-exec pipe and
> piping the error code through in case of failure. In case of success,
> close-on-exec closes the pipe on successful exec and parent process
> gets end of file on read.

Thanks; I think overall this is a good idea, even though I have no clue
if WIN32 side wants a similar support.

 - At first reading, the "while (close(fd) < 0 && errno != EBADF);"
   pattern was a bit of eyesore.  It might be worth factoring that out to
   a small static helper function that a smart compiler would
   automatically inline (or mark it as a static inline).

 - Is it guaranteed that a failed pipe(2) never touches its int fildes[2]
   parameter, or the values are undefined when it fails?  The approach
   would save one extra variable, compared to an alternative approach to
   keep an explicit variable to record a pipe failure, but It feels iffy
   that the code relies on them being left as their initial -1 values.

 - Should we worry about partial write as well (you seem to warn when you
   get a partial read)?  Is it worth using xread() and friends found in
   wrapper.c instead of goto read/write_again?

 - Shouldn't any of these warning() be die() instead?

 - The two extra file descriptors this patch uses are allocated after all
   the existing pipe flipping is done, and all the dup's done in the child
   process are to use dup2() to set up the known file descriptors at low
   numbers, so I don't think we have to worry about this patch changing
   the behaviour of the process pair by changing the assignment of file
   descriptors (we had a bug or two in the past that made subprocess
   misbehave under some funky condition, e.g. run with fd#0 closed).

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 2/2] Improve transport helper exec failure reporting
  2009-12-24 17:49 ` [RFC PATCH 2/2] Improve transport helper exec failure reporting Ilari Liusvaara
@ 2009-12-25  7:44   ` Junio C Hamano
  2009-12-25  9:32     ` Ilari Liusvaara
  0 siblings, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2009-12-25  7:44 UTC (permalink / raw)
  To: Ilari Liusvaara; +Cc: git

Ilari Liusvaara <ilari.liusvaara@elisanet.fi> writes:

> Previously transport-helper exec failure error reporting was pretty
> much useless as it didn't report errors from execve, only from pipe
> and fork. Now that run-command passes errno from exec, use the
> improved support to actually print useful errors if execution fails.
>
> Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>

Looks pretty straightforward, except that I have this nagging feeling that
we should *not* be married to the idea of "'proc->git_cmd = 1' is merely a
way to save you from typing 'git-' prefix in start_command(proc)".

> diff --git a/transport-helper.c b/transport-helper.c
> index 5078c71..0965c9b 100644
> --- a/transport-helper.c
> +++ b/transport-helper.c
> @@ -31,13 +31,19 @@ static struct child_process *get_helper(struct transport *transport)
>  	helper->out = -1;
>  	helper->err = 0;
>  	helper->argv = xcalloc(4, sizeof(*helper->argv));
> -	strbuf_addf(&buf, "remote-%s", data->name);
> +	strbuf_addf(&buf, "git-remote-%s", data->name);
>  	helper->argv[0] = strbuf_detach(&buf, NULL);
>  	helper->argv[1] = transport->remote->name;
>  	helper->argv[2] = transport->url;
> -	helper->git_cmd = 1;
> -	if (start_command(helper))
> -		die("Unable to run helper: git %s", helper->argv[0]);
> +	helper->git_cmd = 0;
> +	if (start_command(helper)) {

For example, we might later want to use different $PATH only when running
a git subcommand, and telling run_command() explicitly that we are running
a git thing would help if you don't add "git-" to the command line and
drop "proc->git_cmd = 1" in the caller like your patch does.

> +		if (errno == ENOENT)
> +			die("Unable to find remote helper for \"%s\"",
> +				data->name);
> +		else
> +			die("Unable to run helper %s: %s", helper->argv[0],
> +				strerror(errno));
> +	}
>  	data->helper = helper;
>  
>  	write_str_in_full(helper->in, "capabilities\n");
> -- 
> 1.6.6.3.gaa2e1

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/2] Report exec errors from run-command
  2009-12-25  7:35   ` Junio C Hamano
@ 2009-12-25  7:46     ` Junio C Hamano
  2009-12-25  8:40     ` Junio C Hamano
  2009-12-25  9:51     ` Ilari Liusvaara
  2 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2009-12-25  7:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Ilari Liusvaara, git

Junio C Hamano <gitster@pobox.com> writes:

> Ilari Liusvaara <ilari.liusvaara@elisanet.fi> writes:
>
>> Previously run-command was unable to report errors happening in exec
>> call. Change it to pass errno from failed exec to errno value at
>> return.
>>
>> The errno value passing can be done by opening close-on-exec pipe and
>> piping the error code through in case of failure. In case of success,
>> close-on-exec closes the pipe on successful exec and parent process
>> gets end of file on read.
>
> Thanks; I think overall this is a good idea, even though I have no clue
> if WIN32 side wants a similar support.

By the way, at least it should be pretty straightforward to add a test or
two for [1/2] if not [2/2].

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/2] Report exec errors from run-command
  2009-12-25  7:35   ` Junio C Hamano
  2009-12-25  7:46     ` Junio C Hamano
@ 2009-12-25  8:40     ` Junio C Hamano
  2009-12-25  9:51     ` Ilari Liusvaara
  2 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2009-12-25  8:40 UTC (permalink / raw)
  To: Ilari Liusvaara; +Cc: git

Junio C Hamano <gitster@pobox.com> writes:

>  - At first reading, the "while (close(fd) < 0 && errno != EBADF);"
>    pattern was a bit of eyesore.  It might be worth factoring that out to
>    a small static helper function that a smart compiler would
>    automatically inline (or mark it as a static inline).

This also is a minor style thing, but we prefer your

>>+		while(close(report_pipe[1]) < 0 && errno != EBADF);

formatted like this:

	while (foobar)
        	; /* noop */

to

 (1) have SP after syntactic keyword like while/if/switch to differentiate
     from function calls; and 

 (2) make the no-op stand out for a bit more visibility.

 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 2/2] Improve transport helper exec failure reporting
  2009-12-25  7:44   ` Junio C Hamano
@ 2009-12-25  9:32     ` Ilari Liusvaara
  0 siblings, 0 replies; 11+ messages in thread
From: Ilari Liusvaara @ 2009-12-25  9:32 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Thu, Dec 24, 2009 at 11:44:49PM -0800, Junio C Hamano wrote:
> Ilari Liusvaara <ilari.liusvaara@elisanet.fi> writes:
> 
> Looks pretty straightforward, except that I have this nagging feeling that
> we should *not* be married to the idea of "'proc->git_cmd = 1' is merely a
> way to save you from typing 'git-' prefix in start_command(proc)".

That is already broken. If nothing previous broke it, then 1/2 of this
series did.

The immediate executable to run for 'git-foo' && git_cmd = 0: 'git-foo'.
The immediate executable to run for 'foo' && git_cmd = 1: 'git'(!).

And one wants exec status for 'git-remote-foo', NOT for 'git'. Thus,
git_cmd must be 0 (at least without additional flags or flag values).
 
> For example, we might later want to use different $PATH only when running
> a git subcommand, and telling run_command() explicitly that we are running
> a git thing would help if you don't add "git-" to the command line and
> drop "proc->git_cmd = 1" in the caller like your patch does.

Well, that would require new flag (or git_cmd field value) to mean do direct
exec with gitexecdir in $PATH. Otherwise, you would either break this piece
of code, or it would be already broken (depending on value of git_cmd).

-Ilari

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/2] Report exec errors from run-command
  2009-12-25  7:35   ` Junio C Hamano
  2009-12-25  7:46     ` Junio C Hamano
  2009-12-25  8:40     ` Junio C Hamano
@ 2009-12-25  9:51     ` Ilari Liusvaara
  2 siblings, 0 replies; 11+ messages in thread
From: Ilari Liusvaara @ 2009-12-25  9:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Thu, Dec 24, 2009 at 11:35:04PM -0800, Junio C Hamano wrote:
> Ilari Liusvaara <ilari.liusvaara@elisanet.fi> writes:
> 
> Thanks; I think overall this is a good idea, even though I have no clue
> if WIN32 side wants a similar support.

It would. But I have no clue about WIN32. But there are other people
on this list who have. :-)
 
>  - At first reading, the "while (close(fd) < 0 && errno != EBADF);"
>    pattern was a bit of eyesore.  It might be worth factoring that out to
>    a small static helper function that a smart compiler would
>    automatically inline (or mark it as a static inline).

Done (with bit of reformatting to add space, line break and comment.

>  - Is it guaranteed that a failed pipe(2) never touches its int fildes[2]
>    parameter, or the values are undefined when it fails?  The approach
>    would save one extra variable, compared to an alternative approach to
>    keep an explicit variable to record a pipe failure, but It feels iffy
>    that the code relies on them being left as their initial -1 values.

I added explicit set to -1 on failure case (I think failed pipe doesn't touch
those, but you never know about what some oddball OS is going to do).

>  - Should we worry about partial write as well (you seem to warn when you
>    get a partial read)?  Is it worth using xread() and friends found in
>    wrapper.c instead of goto read/write_again?

That's hairy code. One really can't print any errors in write path, as those
errors would go to who knows where due to redirections (I took the error
warning out).

That partial read warning is more for detecting 'can't happen' situations
since pipe should be large enough to atomically transfer integer.

>  - Shouldn't any of these warning() be die() instead?

If error reporting failures are fatal, all of them.

-Ilari

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/2] Report exec errors from run-command
  2009-12-24 17:49 ` [RFC PATCH 1/2] Report exec errors from run-command Ilari Liusvaara
  2009-12-25  7:35   ` Junio C Hamano
@ 2009-12-25 14:39   ` Johannes Sixt
  2009-12-25 17:15     ` Ilari Liusvaara
  1 sibling, 1 reply; 11+ messages in thread
From: Johannes Sixt @ 2009-12-25 14:39 UTC (permalink / raw)
  To: Ilari Liusvaara; +Cc: git

On Donnerstag, 24. Dezember 2009, Ilari Liusvaara wrote:
> Previously run-command was unable to report errors happening in exec
> call. Change it to pass errno from failed exec to errno value at
> return.
>
> The errno value passing can be done by opening close-on-exec pipe and
> piping the error code through in case of failure. In case of success,
> close-on-exec closes the pipe on successful exec and parent process
> gets end of file on read.

The only really *important* errno of a failed exec is ENOENT. For this case, 
wouldn't it be easier to do the PATH lookup manually in the parent (before 
the fork()), and use execv() in the forked child rather than execvp()?

There is already a path lookup function in compat/mingw.c; it could certainly 
need some improvement, but it is a starter.

That said, we don't need the stunt that you implemented on WIN32, because by 
the time mingw_spawnvpe() returns, we have a running child process.

-- Hannes

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/2] Report exec errors from run-command
  2009-12-25 14:39   ` Johannes Sixt
@ 2009-12-25 17:15     ` Ilari Liusvaara
  0 siblings, 0 replies; 11+ messages in thread
From: Ilari Liusvaara @ 2009-12-25 17:15 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git

On Fri, Dec 25, 2009 at 03:39:34PM +0100, Johannes Sixt wrote:
> 
> The only really *important* errno of a failed exec is ENOENT. For this case, 
> wouldn't it be easier to do the PATH lookup manually in the parent (before 
> the fork()), and use execv() in the forked child rather than execvp()?

In fact there is API for getting all valid commands on $PATH for given command
prefix. That would take care of ENOENT and most of EACCESS.

But OTOH, its nice to be able to report any error.

-Ilari

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2009-12-25 17:15 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-24 17:49 [RFC PATCH 0/2] Report remote helper exec failures Ilari Liusvaara
2009-12-24 17:49 ` [RFC PATCH 1/2] Report exec errors from run-command Ilari Liusvaara
2009-12-25  7:35   ` Junio C Hamano
2009-12-25  7:46     ` Junio C Hamano
2009-12-25  8:40     ` Junio C Hamano
2009-12-25  9:51     ` Ilari Liusvaara
2009-12-25 14:39   ` Johannes Sixt
2009-12-25 17:15     ` Ilari Liusvaara
2009-12-24 17:49 ` [RFC PATCH 2/2] Improve transport helper exec failure reporting Ilari Liusvaara
2009-12-25  7:44   ` Junio C Hamano
2009-12-25  9:32     ` Ilari Liusvaara

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).