git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* bug & patch: exit codes from internal commands are handled incorrectly
@ 2014-12-16 19:28 Kenneth Lorber
  2014-12-18  2:15 ` Kenneth Lorber
  0 siblings, 1 reply; 8+ messages in thread
From: Kenneth Lorber @ 2014-12-16 19:28 UTC (permalink / raw)
  To: git; +Cc: Kenneth Lorber

(Apologies if I’ve missed anything here - I’m still climbing the git learning curve.)

Bug: exit codes from (at least) internal commands are handled incorrectly.
E.g. git-merge-file, docs say:
        The exit value of this program is negative on error, and the number of
        conflicts otherwise. If the merge was clean, the exit value is 0.
But only 8 bits get carried through exit, so 256 conflicts gives exit(0), which means the merge was clean.

Issue shows up on:
 git version 1.8.5.2 (Apple Git-48)
 build from source (git version 2.2.0.68.g64396d6.dirty after patch below applied)

Reproduce by:

Put the following test program in an empty directory as buggen.pl

TEST PROGRAM START
open OUTB, ">basefile" or die;
print OUTB "this is the base file\n";
close OUTB;

open OUT1, ">bfile1" or die;
open OUT2, ">bfile2" or die;

$c = shift;

while($c > 0){
        print OUT1 "a\nb\nc\nd\nchange $c file 1\n";
        print OUT2 "a\nb\nc\nd\nchange $c file 2\n";
        $c--;
}
TEST PROGRAM END

Do these tests:

perl buggen.pl 0
git merge-file -p bfile1 basefile bfile2
echo $status
0

perl buggen.pl 1
git merge-file -p bfile1 basefile bfile2
echo $status
1

perl buggen.pl 256
git merge-file -p bfile1 basefile bfile2
echo $status
0       <===OOPS

Proposed patches:
diff --git a/git.c b/git.c
index 82d7a1c..8228a3c 100644
--- a/git.c
+++ b/git.c
@@ -349,6 +349,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const
        trace_argv_printf(argv, "trace: built-in: git");

        status = p->fn(argc, argv, prefix);
+       if (status > 255)
+               status = 255;   /* prevent exit() from truncating to 0 */
        if (status)
                return status;
diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index d2fc12e..76e6a11 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -41,7 +41,8 @@ lines from `<other-file>`, or lines from both respectively.  T
 conflict markers can be given with the `--marker-size` option.

 The exit value of this program is negative on error, and the number of
-conflicts otherwise. If the merge was clean, the exit value is 0.
+conflicts otherwise (but 255 will be reported even if more than 255 conflicts
+exist). If the merge was clean, the exit value is 0.

 'git merge-file' is designed to be a minimal clone of RCS 'merge'; that is, it
 implements all of RCS 'merge''s functionality which is needed by

Open questions:
1) Is 255 safe for all operating systems?
2) Does this issue affect any other places?

Thanks,
Keni
keni@his.com

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

* Re: bug & patch: exit codes from internal commands are handled incorrectly
  2014-12-16 19:28 bug & patch: exit codes from internal commands are handled incorrectly Kenneth Lorber
@ 2014-12-18  2:15 ` Kenneth Lorber
  2014-12-18 17:43   ` Torsten Bögershausen
  2014-12-18 19:18   ` Junio C Hamano
  0 siblings, 2 replies; 8+ messages in thread
From: Kenneth Lorber @ 2014-12-18  2:15 UTC (permalink / raw)
  To: git; +Cc: Kenneth Lorber

The situation is actually slightly more complex than I stated previously.  From the docs:
  The exit value of this program is negative on error,
But there’s no such thing as a negative error code under Unix, so (at best) that will be exit(255).

No patch, because this is getting painfully close to needing someone with a global view of the code to fix.

Thanks,
Keni

On Dec 16, 2014, at 2:28 PM, Kenneth Lorber <keni@his.com> wrote:

> (Apologies if I’ve missed anything here - I’m still climbing the git learning curve.)
> 
> Bug: exit codes from (at least) internal commands are handled incorrectly.
> E.g. git-merge-file, docs say:
>        The exit value of this program is negative on error, and the number of
>        conflicts otherwise. If the merge was clean, the exit value is 0.
> But only 8 bits get carried through exit, so 256 conflicts gives exit(0), which means the merge was clean.
> 
> Issue shows up on:
> git version 1.8.5.2 (Apple Git-48)
> build from source (git version 2.2.0.68.g64396d6.dirty after patch below applied)
> 
> Reproduce by:
> 
> Put the following test program in an empty directory as buggen.pl
> 
> TEST PROGRAM START
> open OUTB, ">basefile" or die;
> print OUTB "this is the base file\n";
> close OUTB;
> 
> open OUT1, ">bfile1" or die;
> open OUT2, ">bfile2" or die;
> 
> $c = shift;
> 
> while($c > 0){
>        print OUT1 "a\nb\nc\nd\nchange $c file 1\n";
>        print OUT2 "a\nb\nc\nd\nchange $c file 2\n";
>        $c--;
> }
> TEST PROGRAM END
> 
> Do these tests:
> 
> perl buggen.pl 0
> git merge-file -p bfile1 basefile bfile2
> echo $status
> 0
> 
> perl buggen.pl 1
> git merge-file -p bfile1 basefile bfile2
> echo $status
> 1
> 
> perl buggen.pl 256
> git merge-file -p bfile1 basefile bfile2
> echo $status
> 0       <===OOPS
> 
> Proposed patches:
> diff --git a/git.c b/git.c
> index 82d7a1c..8228a3c 100644
> --- a/git.c
> +++ b/git.c
> @@ -349,6 +349,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const
>        trace_argv_printf(argv, "trace: built-in: git");
> 
>        status = p->fn(argc, argv, prefix);
> +       if (status > 255)
> +               status = 255;   /* prevent exit() from truncating to 0 */
>        if (status)
>                return status;
> diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
> index d2fc12e..76e6a11 100644
> --- a/Documentation/git-merge-file.txt
> +++ b/Documentation/git-merge-file.txt
> @@ -41,7 +41,8 @@ lines from `<other-file>`, or lines from both respectively.  T
> conflict markers can be given with the `--marker-size` option.
> 
> The exit value of this program is negative on error, and the number of
> -conflicts otherwise. If the merge was clean, the exit value is 0.
> +conflicts otherwise (but 255 will be reported even if more than 255 conflicts
> +exist). If the merge was clean, the exit value is 0.
> 
> 'git merge-file' is designed to be a minimal clone of RCS 'merge'; that is, it
> implements all of RCS 'merge''s functionality which is needed by
> 
> Open questions:
> 1) Is 255 safe for all operating systems?
> 2) Does this issue affect any other places?
> 
> Thanks,
> Keni
> keni@his.com
> 

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

* Re: bug & patch: exit codes from internal commands are handled incorrectly
  2014-12-18  2:15 ` Kenneth Lorber
@ 2014-12-18 17:43   ` Torsten Bögershausen
  2014-12-18 19:18   ` Junio C Hamano
  1 sibling, 0 replies; 8+ messages in thread
From: Torsten Bögershausen @ 2014-12-18 17:43 UTC (permalink / raw)
  To: Kenneth Lorber, git

On 18.12.14 03:15, Kenneth Lorber wrote:
> The situation is actually slightly more complex than I stated previously.  From the docs:
>   The exit value of this program is negative on error,
> But there’s no such thing as a negative error code under Unix, so (at best) that will be exit(255).
> 
> No patch, because this is getting painfully close to needing someone with a global view of the code to fix.
> 
> Thanks,
> Keni
> 
My spontanous question:
Would it be save to clamp at 127 ?

>> +       if (status > 127)
>> +               status = 127;   /* prevent exit() from truncating to 0 or becoming negative */


(And the rest looked good enough to become a patch, 
or at least to start a wider discussion)

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

* Re: bug & patch: exit codes from internal commands are handled incorrectly
  2014-12-18  2:15 ` Kenneth Lorber
  2014-12-18 17:43   ` Torsten Bögershausen
@ 2014-12-18 19:18   ` Junio C Hamano
  2014-12-20 12:39     ` Kenneth Lorber
  2015-02-01 22:32     ` Kenneth Lorber
  1 sibling, 2 replies; 8+ messages in thread
From: Junio C Hamano @ 2014-12-18 19:18 UTC (permalink / raw)
  To: Kenneth Lorber; +Cc: git

Kenneth Lorber <keni@his.com> writes:

>> Bug: exit codes from (at least) internal commands are handled incorrectly.
>> E.g. git-merge-file, docs say:
>>        The exit value of this program is negative on error, and the number of
>>        conflicts otherwise. If the merge was clean, the exit value is 0.
>> But only 8 bits get carried through exit, so 256 conflicts gives
>> exit(0), which means the merge was clean.

Wouldn't any cmd_foo() that returns negative to main() be buggy?

Your change sweeps such problems under the rug, which is not a
healthy thing to do.

Expecting that the exit code can signal small positive integers and
other generic kinds of failures is a losing proposition.  I think it
is a better fix to update cmd_merge_file() to return 1 (when ret is
positive), 0 (when ret is zero) or 128 (when ret is negative), or
something simple like that, and update the documentation to match
that, without touching git.c::main().

Among the in-tree users, I notice git-cvsserver.perl is already
using the command incorrectly.  It does this:

            my $return = system("git", "merge-file", $file_local, $file_old, $file_new);
            $return >>= 8;

            cleanupTmpDir();

            if ( $return == 0 )
            {
                $log->info("Merged successfully");
                ...
            }
            elsif ( $return == 1 )
            {
                $log->info("Merged with conflicts");
                ...
            }
            else
            {
                $log->warn("Merge failed");
                next;
            }

which assumes $return == 1 is special "half-good", which is not
consistent with the documented interface.  It will incorrectly
say "Merge failed" when there are two or more conflicts.

And with such a "1 or 0 or -1" change, you will fix that caller as
well ;-)

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

* Re: bug & patch: exit codes from internal commands are handled incorrectly
  2014-12-18 19:18   ` Junio C Hamano
@ 2014-12-20 12:39     ` Kenneth Lorber
  2015-02-01 22:32     ` Kenneth Lorber
  1 sibling, 0 replies; 8+ messages in thread
From: Kenneth Lorber @ 2014-12-20 12:39 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git


On Dec 18, 2014, at 2:18 PM, Junio C Hamano <gitster@pobox.com> wrote:

> Kenneth Lorber <keni@his.com> writes:
> 
>>> Bug: exit codes from (at least) internal commands are handled incorrectly.
>>> E.g. git-merge-file, docs say:
>>>       The exit value of this program is negative on error, and the number of
>>>       conflicts otherwise. If the merge was clean, the exit value is 0.
>>> But only 8 bits get carried through exit, so 256 conflicts gives
>>> exit(0), which means the merge was clean.
> 
> Wouldn't any cmd_foo() that returns negative to main() be buggy?

Absolutely.

> Your change sweeps such problems under the rug, which is not a
> healthy thing to do.

True.  But as I don’t know the codebase it seemed the safe thing to do
at least to prove the bug existed before filing a bug report.

> Expecting that the exit code can signal small positive integers and
> other generic kinds of failures is a losing proposition.  I think it
> is a better fix to update cmd_merge_file() to return 1 (when ret is
> positive), 0 (when ret is zero) or 128 (when ret is negative), or
> something simple like that, and update the documentation to match
> that, without touching git.c::main().

I agree.

It does leave open the question of whether this bit of information
is of any use and should/could be reported out in another way.  It’s not
to me, so I won’t be proposing anything to address that.

> Among the in-tree users, I notice git-cvsserver.perl is already
> using the command incorrectly.  It does this:
> 
>            my $return = system("git", "merge-file", $file_local, $file_old, $file_new);
>            $return >>= 8;
> 
>            cleanupTmpDir();
> 
>            if ( $return == 0 )
>            {
>                $log->info("Merged successfully");
>                ...
>            }
>            elsif ( $return == 1 )
>            {
>                $log->info("Merged with conflicts");
>                ...
>            }
>            else
>            {
>                $log->warn("Merge failed");
>                next;
>            }
> 
> which assumes $return == 1 is special "half-good", which is not
> consistent with the documented interface.  It will incorrectly
> say "Merge failed" when there are two or more conflicts.
> 
> And with such a "1 or 0 or -1" change, you will fix that caller as
> well ;-)

Yay! :-)

Thanks,
Keni

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

* Re: bug & patch: exit codes from internal commands are handled incorrectly
  2014-12-18 19:18   ` Junio C Hamano
  2014-12-20 12:39     ` Kenneth Lorber
@ 2015-02-01 22:32     ` Kenneth Lorber
  2015-04-01  0:10       ` Kenneth Lorber
  1 sibling, 1 reply; 8+ messages in thread
From: Kenneth Lorber @ 2015-02-01 22:32 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Kenneth Lorber

[-- Attachment #1: Type: text/plain, Size: 2727 bytes --]


On Dec 18, 2014, at 2:18 PM, Junio C Hamano <gitster@pobox.com> wrote:

> Kenneth Lorber <keni@his.com> writes:
> 
>>> Bug: exit codes from (at least) internal commands are handled incorrectly.
>>> E.g. git-merge-file, docs say:
>>>       The exit value of this program is negative on error, and the number of
>>>       conflicts otherwise. If the merge was clean, the exit value is 0.
>>> But only 8 bits get carried through exit, so 256 conflicts gives
>>> exit(0), which means the merge was clean.
> 
> Wouldn't any cmd_foo() that returns negative to main() be buggy?

Yes.

> 
> Your change sweeps such problems under the rug, which is not a
> healthy thing to do.

Agreed.  (See below.)

> 
> Expecting that the exit code can signal small positive integers and
> other generic kinds of failures is a losing proposition.  I think it
> is a better fix to update cmd_merge_file() to return 1 (when ret is
> positive), 0 (when ret is zero) or 128 (when ret is negative), or
> something simple like that, and update the documentation to match
> that, without touching git.c::main().

The new patch uses 0, 1, and 2 to match diff(1).

> Among the in-tree users, I notice git-cvsserver.perl is already
> using the command incorrectly.  It does this:
> 
>            my $return = system("git", "merge-file", $file_local, $file_old, $file_new);
>            $return >>= 8;
> 
>            cleanupTmpDir();
> 
>            if ( $return == 0 )
>            {
>                $log->info("Merged successfully");
>                ...
>            }
>            elsif ( $return == 1 )
>            {
>                $log->info("Merged with conflicts");
>                ...
>            }
>            else
>            {
>                $log->warn("Merge failed");
>                next;
>            }
> 
> which assumes $return == 1 is special "half-good", which is not
> consistent with the documented interface.  It will incorrectly
> say "Merge failed" when there are two or more conflicts.
> 
> And with such a "1 or 0 or -1" change, you will fix that caller as
> well ;-)

I'll call that a win.

The attached patch covers the following:
- fixes all places where "make test" attempts to call exit() with a value <0 or >255
- changes git-merge-file.txt to reflect the change in exit codes
- fixes the exit codes for merge-file
- adds a warning (which should probably be changed to something clearer) if git.c:run_builtin() is going to cause an out-of-bounds exit
- fixes a typo in t7007-show.sh
- replaces return(0) with exit(0) in test-parse-options.c

The diff is cut against 15598cf41beed0d86cd2ac443e0f69c5a3b40321 (2.3.0-rc2)

Thanks,
Keni



[-- Attachment #2: d2.ship --]
[-- Type: application/octet-stream, Size: 8475 bytes --]

diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index d2fc12e..425dba3 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -40,8 +40,8 @@ however, these conflicts are resolved favouring lines from `<current-file>`,
 lines from `<other-file>`, or lines from both respectively.  The length of the
 conflict markers can be given with the `--marker-size` option.
 
-The exit value of this program is negative on error, and the number of
-conflicts otherwise. If the merge was clean, the exit value is 0.
+The exit value of this program is 0 if the merge was clean, 1 if there were
+conflicts, and 2 if an error occured.
 
 'git merge-file' is designed to be a minimal clone of RCS 'merge'; that is, it
 implements all of RCS 'merge''s functionality which is needed by
diff --git a/builtin/branch.c b/builtin/branch.c
index dc6f0b2..e586846 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -938,10 +938,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			strbuf_release(&branch_ref);
 
 			if (!argc)
-				return error(_("No commit on branch '%s' yet."),
+				return -error(_("No commit on branch '%s' yet."),
 					     branch_name);
 			else
-				return error(_("No branch named '%s'."),
+				return -error(_("No branch named '%s'."),
 					     branch_name);
 		}
 		strbuf_release(&branch_ref);
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 5600ec3..62cacf3 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -169,7 +169,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
 			name = argv[i];
 			a = git_attr(name);
 			if (!a)
-				return error("%s: not a valid attribute name",
+				return -error("%s: not a valid attribute name",
 					name);
 			check[i].attr = a;
 		}
diff --git a/builtin/config.c b/builtin/config.c
index 15a7bea..23aab25 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -667,7 +667,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		ret = git_config_rename_section_in_file(given_config_source.file,
 							argv[0], argv[1]);
 		if (ret < 0)
-			return ret;
+			return -ret;
 		if (ret == 0)
 			die("No such section!");
 	}
@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		ret = git_config_rename_section_in_file(given_config_source.file,
 							argv[0], NULL);
 		if (ret < 0)
-			return ret;
+			return -ret;
 		if (ret == 0)
 			die("No such section!");
 	}
diff --git a/builtin/log.c b/builtin/log.c
index 923ffe7..cb6914b 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -561,7 +561,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 				break;
 			o = parse_object(t->tagged->sha1);
 			if (!o)
-				ret = error(_("Could not read object %s"),
+				ret = -error(_("Could not read object %s"),
 					    sha1_to_hex(t->tagged->sha1));
 			objects[i].item = o;
 			i--;
@@ -585,7 +585,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 			ret = cmd_log_walk(&rev);
 			break;
 		default:
-			ret = error(_("Unknown type: %d"), o->type);
+			ret = -error(_("Unknown type: %d"), o->type);
 		}
 	}
 	free(objects);
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index 844f84f..8dfb42c 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -61,9 +61,11 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 	if (argc != 3)
 		usage_with_options(merge_file_usage, options);
 	if (quiet) {
-		if (!freopen("/dev/null", "w", stderr))
-			return error("failed to redirect stderr to /dev/null: "
+		if (!freopen("/dev/null", "w", stderr)) {
+			error("failed to redirect stderr to /dev/null: "
 				     "%s", strerror(errno));
+			return 2;
+		}
 	}
 
 	if (prefix)
@@ -74,10 +76,12 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 		if (!names[i])
 			names[i] = argv[i];
 		if (read_mmfile(mmfs + i, fname))
-			return -1;
-		if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
-			return error("Cannot merge binary files: %s",
+			return 2;
+		if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size)) {
+			error("Cannot merge binary files: %s",
 					argv[i]);
+			return 2;
+		}
 	}
 
 	xmp.ancestor = names[1];
@@ -100,7 +104,11 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 		else if (fclose(f))
 			ret = error("Could not close %s", filename);
 		free(result.ptr);
+
+		if (ret == -1) return 2;	/* error */
+		if (ret == 0) return 0;		/* no conflicts */
+		return 1;			/* conflicts */
 	}
 
-	return ret;
+	return 2;	/* error */
 }
diff --git a/builtin/replace.c b/builtin/replace.c
index 85d39b5..5ff7ee1 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -299,7 +299,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw)
 	free(tmpfile);
 
 	if (!hashcmp(old, new))
-		return error("new object is the same as the old one: '%s'", sha1_to_hex(old));
+		return -error("new object is the same as the old one: '%s'", sha1_to_hex(old));
 
 	return replace_object_sha1(object_ref, old, "replacement", new, force);
 }
@@ -410,7 +410,7 @@ static int create_graft(int argc, const char **argv, int force)
 	strbuf_release(&buf);
 
 	if (!hashcmp(old, new))
-		return error("new commit is the same as the old one: '%s'", sha1_to_hex(old));
+		return -error("new commit is the same as the old one: '%s'", sha1_to_hex(old));
 
 	return replace_object_sha1(old_ref, old, "replacement", new, force);
 }
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index b564a77..7b7f6cd 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -277,7 +277,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 
 	/* match them up */
 	if (match_push_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
-		return -1;
+		return 1;
 
 	if (!is_empty_cas(&cas))
 		apply_push_cas(&cas, remote, remote_refs);
@@ -307,5 +307,5 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 	if (!ret && !transport_refs_pushed(remote_refs))
 		fprintf(stderr, "Everything up-to-date\n");
 
-	return ret;
+	return (ret<0) ? -ret : ret;
 }
diff --git a/git.c b/git.c
index 6b5ae6a..b6a75e9 100644
--- a/git.c
+++ b/git.c
@@ -346,6 +346,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 	trace_argv_printf(argv, "trace: built-in: git");
 
 	status = p->fn(argc, argv, prefix);
+	if(status < 0 || status >255)
+		warning("internal bad status (no effect on the git command)");
 	if (status)
 		return status;
 
diff --git a/run-command.c b/run-command.c
index 0b432cc..353acc8 100644
--- a/run-command.c
+++ b/run-command.c
@@ -567,6 +567,14 @@ int run_command(struct child_process *cmd)
 	return finish_command(cmd);
 }
 
+int run_command2(struct child_process *cmd)
+{
+	int code = start_command(cmd);
+	if (code)
+		return code<0 ? -code : code;
+	return finish_command(cmd);
+}
+
 int run_command_v_opt(const char **argv, int opt)
 {
 	return run_command_v_opt_cd_env(argv, opt, NULL, NULL);
diff --git a/run-command.h b/run-command.h
index d6868dc..afa0212 100644
--- a/run-command.h
+++ b/run-command.h
@@ -51,6 +51,7 @@ void child_process_init(struct child_process *);
 int start_command(struct child_process *);
 int finish_command(struct child_process *);
 int run_command(struct child_process *);
+int run_command2(struct child_process *);
 
 extern char *find_hook(const char *name);
 LAST_ARG_MUST_BE_NULL
diff --git a/t/t7007-show.sh b/t/t7007-show.sh
index 1b824fe..e7272bb 100755
--- a/t/t7007-show.sh
+++ b/t/t7007-show.sh
@@ -13,7 +13,7 @@ test_expect_success setup '
 	rm -f .git/objects/$HH/$H38
 '
 
-test_expect_success 'showing a tag that point at a missing object' '
+test_expect_success 'showing a tag that points at a missing object' '
 	test_must_fail git --no-pager show foo-tag
 '
 
diff --git a/test-parse-options.c b/test-parse-options.c
index 5dabce6..8dba84f 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -97,5 +97,5 @@ int main(int argc, char **argv)
 	for (i = 0; i < argc; i++)
 		printf("arg %02d: %s\n", i, argv[i]);
 
-	return 0;
+	exit(0);
 }
diff --git a/test-run-command.c b/test-run-command.c
index 89c7de2..4d8c230 100644
--- a/test-run-command.c
+++ b/test-run-command.c
@@ -28,7 +28,7 @@ int main(int argc, char **argv)
 		return 1;
 	}
 	if (!strcmp(argv[1], "run-command"))
-		exit(run_command(&proc));
+		exit(run_command2(&proc));
 
 	fprintf(stderr, "check usage\n");
 	return 1;

[-- Attachment #3: Type: text/plain, Size: 2 bytes --]




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

* Re: bug & patch: exit codes from internal commands are handled incorrectly
  2015-02-01 22:32     ` Kenneth Lorber
@ 2015-04-01  0:10       ` Kenneth Lorber
  2015-04-01  0:40         ` Junio C Hamano
  0 siblings, 1 reply; 8+ messages in thread
From: Kenneth Lorber @ 2015-04-01  0:10 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Kenneth Lorber

Ping?  The original version of this got some discussion, but this version - nothing.

Thanks,
Keni

On Feb 1, 2015, at 5:32 PM, Kenneth Lorber <keni@his.com> wrote:

> 
> On Dec 18, 2014, at 2:18 PM, Junio C Hamano <gitster@pobox.com> wrote:
> 
>> Kenneth Lorber <keni@his.com> writes:
>> 
>>>> Bug: exit codes from (at least) internal commands are handled incorrectly.
>>>> E.g. git-merge-file, docs say:
>>>>      The exit value of this program is negative on error, and the number of
>>>>      conflicts otherwise. If the merge was clean, the exit value is 0.
>>>> But only 8 bits get carried through exit, so 256 conflicts gives
>>>> exit(0), which means the merge was clean.
>> 
>> Wouldn't any cmd_foo() that returns negative to main() be buggy?
> 
> Yes.
> 
>> 
>> Your change sweeps such problems under the rug, which is not a
>> healthy thing to do.
> 
> Agreed.  (See below.)
> 
>> 
>> Expecting that the exit code can signal small positive integers and
>> other generic kinds of failures is a losing proposition.  I think it
>> is a better fix to update cmd_merge_file() to return 1 (when ret is
>> positive), 0 (when ret is zero) or 128 (when ret is negative), or
>> something simple like that, and update the documentation to match
>> that, without touching git.c::main().
> 
> The new patch uses 0, 1, and 2 to match diff(1).
> 
>> Among the in-tree users, I notice git-cvsserver.perl is already
>> using the command incorrectly.  It does this:
>> 
>>           my $return = system("git", "merge-file", $file_local, $file_old, $file_new);
>>           $return >>= 8;
>> 
>>           cleanupTmpDir();
>> 
>>           if ( $return == 0 )
>>           {
>>               $log->info("Merged successfully");
>>               ...
>>           }
>>           elsif ( $return == 1 )
>>           {
>>               $log->info("Merged with conflicts");
>>               ...
>>           }
>>           else
>>           {
>>               $log->warn("Merge failed");
>>               next;
>>           }
>> 
>> which assumes $return == 1 is special "half-good", which is not
>> consistent with the documented interface.  It will incorrectly
>> say "Merge failed" when there are two or more conflicts.
>> 
>> And with such a "1 or 0 or -1" change, you will fix that caller as
>> well ;-)
> 
> I'll call that a win.
> 
> The attached patch covers the following:
> - fixes all places where "make test" attempts to call exit() with a value <0 or >255
> - changes git-merge-file.txt to reflect the change in exit codes
> - fixes the exit codes for merge-file
> - adds a warning (which should probably be changed to something clearer) if git.c:run_builtin() is going to cause an out-of-bounds exit
> - fixes a typo in t7007-show.sh
> - replaces return(0) with exit(0) in test-parse-options.c
> 
> The diff is cut against 15598cf41beed0d86cd2ac443e0f69c5a3b40321 (2.3.0-rc2)
> 
> Thanks,
> Keni
> 
> 
> <d2.ship>
> 

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

* Re: bug & patch: exit codes from internal commands are handled incorrectly
  2015-04-01  0:10       ` Kenneth Lorber
@ 2015-04-01  0:40         ` Junio C Hamano
  0 siblings, 0 replies; 8+ messages in thread
From: Junio C Hamano @ 2015-04-01  0:40 UTC (permalink / raw)
  To: Kenneth Lorber; +Cc: Git Mailing List

On Tue, Mar 31, 2015 at 5:10 PM, Kenneth Lorber <keni@his.com> wrote:
> Ping?  The original version of this got some discussion, but this version - nothing.

Pong? I do not know what you meant by "this version".

Have you followed Documentaiton/SubmittingPatches? Otherwise the
mailing list may have dropped the message.

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

end of thread, other threads:[~2015-04-01  0:40 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-16 19:28 bug & patch: exit codes from internal commands are handled incorrectly Kenneth Lorber
2014-12-18  2:15 ` Kenneth Lorber
2014-12-18 17:43   ` Torsten Bögershausen
2014-12-18 19:18   ` Junio C Hamano
2014-12-20 12:39     ` Kenneth Lorber
2015-02-01 22:32     ` Kenneth Lorber
2015-04-01  0:10       ` Kenneth Lorber
2015-04-01  0:40         ` Junio C Hamano

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