{"thread":{"id":"20024","subject":"[PATCH 2/7] MinGW: simplify waitpid() emulation macros","startedAt":"2009-07-04T19:26:36Z","lastAt":"2009-07-06T07:37:35Z","messageCount":12,"participants":["Johannes Sixt","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"117441","messageId":"cover.1246734159.git.j6t@kdbg.org","threadId":"20024","inReplyTo":null,"subject":"[PATCH 0/7] rework run_command error reporting","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-04T19:26:36Z","receivedAt":"2009-07-04T19:26:36Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"I got tired of thinking about which return values of run_command functions\nare exit codes and which are error codes of system call failures.\n\nFurthermore, it is a pitty that almost no run_command callers correctly\nreport system call failures.\n\nBut on top of all I find it unacceptable that recent git-daemon logs\n\"unable to run 'git-pack-objects'\" if a client terminates the connection\nearly.\n\nThis series addresses these issues, and also fixes an error in git-bisect\non Windows.\n\n1/7 Truncate result of run_command that is used in exit() to lowest 8 bits\n\n    This one fixes a breakage of git-bisect on Windows and should be\n    applied at any rate.\n\n2/7 MinGW: simplify waitpid() emulation macros\n3/7 run_command: return exit code as positive value\n4/7 run_command: report system call errors instead of returning error codes\n\n    These address the mentioned issues; 4/7 is the important change.\n\n5/7 run_command: encode deadly signal number in the return value\n6/7 run_command: report failure to execute the program, but optionally don't\n\n    These two are nice to have.\n\n7/7 receive-pack: remove unnecessary run_status report\n\n    This one is actually RFC because it removes a status report that users\n    might be used to see, or even depend on.\n\n\n bisect.c                     |    4 +-\n builtin-add.c                |    2 +-\n builtin-merge.c              |    2 +-\n builtin-receive-pack.c       |   38 ++--------------\n compat/mingw.h               |    5 +-\n convert.c                    |    2 +-\n git.c                        |   10 +---\n ll-merge.c                   |    4 --\n run-command.c                |  105 +++++++++++++++++++++++------------------\n run-command.h                |   13 +----\n t/t5530-upload-pack-error.sh |    5 ++-\n transport.c                  |   16 +------\n 12 files changed, 81 insertions(+), 125 deletions(-)\n"},{"id":"117442","messageId":"b73cf4b4cd09f4225098e71182044f64e12380aa.1246734159.git.j6t@kdbg.org","threadId":"20024","inReplyTo":"cover.1246734159.git.j6t@kdbg.org","subject":"[PATCH 1/7] Truncate result of run_command that is used in exit() to lowest 8 bits","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-04T19:26:37Z","receivedAt":"2009-07-04T19:26:37Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Windows, negative return values are not detected reliably by the parent\nprocess as failure. This fixes it.\n\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n bisect.c      |    4 ++--\n builtin-add.c |    2 +-\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 52220df..b395c47 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -760,7 +760,7 @@ static int bisect_checkout(char *bisect_rev_hex)\n \targv_checkout[2] = bisect_rev_hex;\n \tres = run_command_v_opt(argv_checkout, RUN_GIT_CMD);\n \tif (res)\n-\t\texit(res);\n+\t\texit(res & 0xff);\n \n \targv_show_branch[1] = bisect_rev_hex;\n \treturn run_command_v_opt(argv_show_branch, RUN_GIT_CMD);\n@@ -850,7 +850,7 @@ static void check_merge_bases(void)\n \t\t\thandle_skipped_merge_base(mb);\n \t\t} else {\n \t\t\tprintf(\"Bisecting: a merge base must be tested\\n\");\n-\t\t\texit(bisect_checkout(sha1_to_hex(mb)));\n+\t\t\texit(bisect_checkout(sha1_to_hex(mb)) & 0xff);\n \t\t}\n \t}\n \ndiff --git a/builtin-add.c b/builtin-add.c\nindex 4e44148..d83e67e 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -305,7 +305,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \tif (patch_interactive)\n \t\tadd_interactive = 1;\n \tif (add_interactive)\n-\t\texit(interactive_add(argc - 1, argv + 1, prefix));\n+\t\texit(interactive_add(argc - 1, argv + 1, prefix) & 0xff);\n \n \tif (edit_interactive)\n \t\treturn(edit_patch(argc, argv, prefix));\n-- \n1.6.3.17.g1665f\n"},{"id":"117440","messageId":"d63e9230d57698a058c8a550709155e5e3222348.1246734159.git.j6t@kdbg.org","threadId":"20024","inReplyTo":"b73cf4b4cd09f4225098e71182044f64e12380aa.1246734159.git.j6t@kdbg.org","subject":"[PATCH 2/7] MinGW: simplify waitpid() emulation macros","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-04T19:26:38Z","receivedAt":"2009-07-04T19:26:38Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Windows does not have signals. At least they cannot be diagnosed by the\nparent process; all that the parent process can observe is the exit code.\n\nThis also adds a dummy definition of WTERMSIG.\n\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n The dummy definition WTERMSIG will be used in a subsequent patch.\n\n compat/mingw.h |    5 +++--\n 1 files changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 4f7ba4c..21ab124 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -17,9 +17,10 @@ typedef int pid_t;\n #define S_IROTH 0\n #define S_IXOTH 0\n \n-#define WIFEXITED(x) ((unsigned)(x) < 259)\t/* STILL_ACTIVE */\n+#define WIFEXITED(x) 1\n+#define WIFSIGNALED(x) 0\n #define WEXITSTATUS(x) ((x) & 0xff)\n-#define WIFSIGNALED(x) ((unsigned)(x) > 259)\n+#define WTERMSIG(x) SIGTERM\n \n #define SIGHUP 1\n #define SIGQUIT 3\n-- \n1.6.3.17.g1665f\n"},{"id":"117445","messageId":"4fe5ad61e7500735d1bbc12c98a863dd3499ea31.1246734159.git.j6t@kdbg.org","threadId":"20024","inReplyTo":"d63e9230d57698a058c8a550709155e5e3222348.1246734159.git.j6t@kdbg.org","subject":"[PATCH 3/7] run_command: return exit code as positive value","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-04T19:26:39Z","receivedAt":"2009-07-04T19:26:39Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"As a general guideline, functions in git's code return zero to indicate\nsuccess and negative values to indicate failure. The run_command family of\nfunctions followed this guideline. But there are actually two different\nkinds of failure:\n\n- failures of system calls;\n\n- non-zero exit code of the program that was run.\n\nUsually, a non-zero exit code of the program is a failure and means a\nfailure to the caller. Except that sometimes it does not. For example, the\nexit code of merge programs (e.g. external merge drivers) conveys\ninformation about how the merge failed, and not all exit calls are\nactually failures.\n\nFurthermore, the return value of run_command is sometimes used as exit\ncode by the caller.\n\nThis change arranges that the exit code of the program is returned as a\npositive value, which can now be regarded as the \"result\" of the function.\nSystem call failures continue to be reported as negative values.\n\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n builtin-merge.c        |    2 +-\n builtin-receive-pack.c |    4 ++--\n convert.c              |    2 +-\n git.c                  |    4 ++--\n ll-merge.c             |    4 ----\n run-command.c          |    9 +--------\n run-command.h          |    1 -\n 7 files changed, 7 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex af9adab..96ecaf4 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -594,7 +594,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,\n \t\tdiscard_cache();\n \t\tif (read_cache() < 0)\n \t\t\tdie(\"failed to read the cache\");\n-\t\treturn -ret;\n+\t\treturn ret;\n \t}\n }\n \ndiff --git a/builtin-receive-pack.c b/builtin-receive-pack.c\nindex 6ec1d05..6235903 100644\n--- a/builtin-receive-pack.c\n+++ b/builtin-receive-pack.c\n@@ -143,8 +143,8 @@ static int run_status(int code, const char *cmd_name)\n \tcase -ERR_RUN_COMMAND_WAITPID_NOEXIT:\n \t\treturn error(\"%s died strangely\", cmd_name);\n \tdefault:\n-\t\terror(\"%s exited with error code %d\", cmd_name, -code);\n-\t\treturn -code;\n+\t\terror(\"%s exited with error code %d\", cmd_name, code);\n+\t\treturn code;\n \t}\n }\n \ndiff --git a/convert.c b/convert.c\nindex 1816e97..491e714 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -267,7 +267,7 @@ static int filter_buffer(int fd, void *data)\n \n \tstatus = finish_command(&child_process);\n \tif (status)\n-\t\terror(\"external filter %s failed %d\", params->cmd, -status);\n+\t\terror(\"external filter %s failed %d\", params->cmd, status);\n \treturn (write_err || status);\n }\n \ndiff --git a/git.c b/git.c\nindex f4d53f4..662f21e 100644\n--- a/git.c\n+++ b/git.c\n@@ -418,9 +418,9 @@ static void execv_dashed_external(const char **argv)\n \t */\n \tstatus = run_command_v_opt(argv, 0);\n \tif (status != -ERR_RUN_COMMAND_EXEC) {\n-\t\tif (IS_RUN_COMMAND_ERR(status))\n+\t\tif (status < 0)\n \t\t\tdie(\"unable to run '%s'\", argv[0]);\n-\t\texit(-status);\n+\t\texit(status);\n \t}\n \terrno = ENOENT; /* as if we called execvp */\n \ndiff --git a/ll-merge.c b/ll-merge.c\nindex a2c13c4..31c7457 100644\n--- a/ll-merge.c\n+++ b/ll-merge.c\n@@ -192,10 +192,6 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,\n \n \targs[2] = cmd.buf;\n \tstatus = run_command_v_opt(args, 0);\n-\tif (status < -ERR_RUN_COMMAND_FORK)\n-\t\t; /* failure in run-command */\n-\telse\n-\t\tstatus = -status;\n \tfd = open(temp[1], O_RDONLY);\n \tif (fd < 0)\n \t\tgoto bad;\ndiff --git a/run-command.c b/run-command.c\nindex eb2efc3..a4e309e 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -241,14 +241,7 @@ static int wait_or_whine(pid_t pid)\n \t\tif (!WIFEXITED(status))\n \t\t\treturn -ERR_RUN_COMMAND_WAITPID_NOEXIT;\n \t\tcode = WEXITSTATUS(status);\n-\t\tswitch (code) {\n-\t\tcase 127:\n-\t\t\treturn -ERR_RUN_COMMAND_EXEC;\n-\t\tcase 0:\n-\t\t\treturn 0;\n-\t\tdefault:\n-\t\t\treturn -code;\n-\t\t}\n+\t\treturn code == 127 ? -ERR_RUN_COMMAND_EXEC : code;\n \t}\n }\n \ndiff --git a/run-command.h b/run-command.h\nindex e345502..0211e1d 100644\n--- a/run-command.h\n+++ b/run-command.h\n@@ -10,7 +10,6 @@ enum {\n \tERR_RUN_COMMAND_WAITPID_SIGNAL,\n \tERR_RUN_COMMAND_WAITPID_NOEXIT,\n };\n-#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK)\n \n struct child_process {\n \tconst char **argv;\n-- \n1.6.3.17.g1665f\n"},{"id":"117444","messageId":"ea2d8110ea70b8698bb3674ca4482db64053d841.1246734159.git.j6t@kdbg.org","threadId":"20024","inReplyTo":"4fe5ad61e7500735d1bbc12c98a863dd3499ea31.1246734159.git.j6t@kdbg.org","subject":"[PATCH 4/7] run_command: report system call errors instead of returning error codes","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-04T19:26:40Z","receivedAt":"2009-07-04T19:26:40Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"The motivation for this change is that system call failures are serious\nerrors that should be reported to the user, but only few callers took the\nburden to decode the error codes that the functions returned into error\nmessages.\n\nIf at all, then only an unspecific error message was given. A prominent\nexample is this:\n\n   $ git upload-pack . | :\n   fatal: unable to run 'git-upload-pack'\n\nIn this example, git-upload-pack, the external command invoked through the\ngit wrapper, dies due to SIGPIPE, but the git wrapper does not bother to\nreport the real cause. In fact, this very error message is copied to the\nsyslog if git-daemon's client aborts the connection early.\n\nWith this change, system call failures are reported immediately after the\nfailure and only a generic failure code is returned to the caller. In the\nabove example the error is now to the point:\n\n   $ git upload-pack . | :\n   error: git-upload-pack died of signal\n\nNote that there is no error report if the invoked program terminated with\na non-zero exit code, because it is reasonable to expect that the invoked\nprogram has already reported an error. (But many run_command call sites\nnevertheless write a generic error message.)\n\nThere was one special return code that was used to identify the case where\nrun_command failed because the requested program could not be exec'd. This\nspecial case is now treated like a system call failure with errno set to\nENOENT. No error is reported in this case, because the call site in git.c\nexpects this as a normal result. Therefore, the callers that carefully\ndecoded the return value still check for this condition.\n\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n builtin-receive-pack.c       |   22 +---------\n git.c                        |    8 +---\n run-command.c                |   89 +++++++++++++++++++++++-------------------\n run-command.h                |   10 -----\n t/t5530-upload-pack-error.sh |    5 ++-\n transport.c                  |   12 +-----\n 6 files changed, 59 insertions(+), 87 deletions(-)\n\ndiff --git a/builtin-receive-pack.c b/builtin-receive-pack.c\nindex 6235903..1dcdb1a 100644\n--- a/builtin-receive-pack.c\n+++ b/builtin-receive-pack.c\n@@ -125,27 +125,11 @@ static const char post_receive_hook[] = \"hooks/post-receive\";\n \n static int run_status(int code, const char *cmd_name)\n {\n-\tswitch (code) {\n-\tcase 0:\n-\t\treturn 0;\n-\tcase -ERR_RUN_COMMAND_FORK:\n-\t\treturn error(\"fork of %s failed\", cmd_name);\n-\tcase -ERR_RUN_COMMAND_EXEC:\n+\tif (code < 0 && errno == ENOENT)\n \t\treturn error(\"execute of %s failed\", cmd_name);\n-\tcase -ERR_RUN_COMMAND_PIPE:\n-\t\treturn error(\"pipe failed\");\n-\tcase -ERR_RUN_COMMAND_WAITPID:\n-\t\treturn error(\"waitpid failed\");\n-\tcase -ERR_RUN_COMMAND_WAITPID_WRONG_PID:\n-\t\treturn error(\"waitpid is confused\");\n-\tcase -ERR_RUN_COMMAND_WAITPID_SIGNAL:\n-\t\treturn error(\"%s died of signal\", cmd_name);\n-\tcase -ERR_RUN_COMMAND_WAITPID_NOEXIT:\n-\t\treturn error(\"%s died strangely\", cmd_name);\n-\tdefault:\n+\telse if (code > 0)\n \t\terror(\"%s exited with error code %d\", cmd_name, code);\n-\t\treturn code;\n-\t}\n+\treturn code;\n }\n \n static int run_receive_hook(const char *hook_name)\ndiff --git a/git.c b/git.c\nindex 662f21e..2fb7093 100644\n--- a/git.c\n+++ b/git.c\n@@ -417,12 +417,8 @@ static void execv_dashed_external(const char **argv)\n \t * OK to return. Otherwise, we just pass along the status code.\n \t */\n \tstatus = run_command_v_opt(argv, 0);\n-\tif (status != -ERR_RUN_COMMAND_EXEC) {\n-\t\tif (status < 0)\n-\t\t\tdie(\"unable to run '%s'\", argv[0]);\n-\t\texit(status);\n-\t}\n-\terrno = ENOENT; /* as if we called execvp */\n+\tif (status >= 0 || errno != ENOENT)\n+\t\texit(status & 0xff);\n \n \targv[0] = tmp;\n \ndiff --git a/run-command.c b/run-command.c\nindex a4e309e..4b3fda0 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -19,6 +19,7 @@ int start_command(struct child_process *cmd)\n {\n \tint need_in, need_out, need_err;\n \tint fdin[2], fdout[2], fderr[2];\n+\tint failed_errno;\n \n \t/*\n \t * In case of errors we must keep the promise to close FDs\n@@ -28,9 +29,10 @@ int start_command(struct child_process *cmd)\n \tneed_in = !cmd->no_stdin && cmd->in < 0;\n \tif (need_in) {\n \t\tif (pipe(fdin) < 0) {\n+\t\t\tfailed_errno = errno;\n \t\t\tif (cmd->out > 0)\n \t\t\t\tclose(cmd->out);\n-\t\t\treturn -ERR_RUN_COMMAND_PIPE;\n+\t\t\tgoto fail_pipe;\n \t\t}\n \t\tcmd->in = fdin[1];\n \t}\n@@ -40,11 +42,12 @@ int start_command(struct child_process *cmd)\n \t\t&& cmd->out < 0;\n \tif (need_out) {\n \t\tif (pipe(fdout) < 0) {\n+\t\t\tfailed_errno = errno;\n \t\t\tif (need_in)\n \t\t\t\tclose_pair(fdin);\n \t\t\telse if (cmd->in)\n \t\t\t\tclose(cmd->in);\n-\t\t\treturn -ERR_RUN_COMMAND_PIPE;\n+\t\t\tgoto fail_pipe;\n \t\t}\n \t\tcmd->out = fdout[0];\n \t}\n@@ -52,6 +55,7 @@ int start_command(struct child_process *cmd)\n \tneed_err = !cmd->no_stderr && cmd->err < 0;\n \tif (need_err) {\n \t\tif (pipe(fderr) < 0) {\n+\t\t\tfailed_errno = errno;\n \t\t\tif (need_in)\n \t\t\t\tclose_pair(fdin);\n \t\t\telse if (cmd->in)\n@@ -60,7 +64,11 @@ int start_command(struct child_process *cmd)\n \t\t\t\tclose_pair(fdout);\n \t\t\telse if (cmd->out)\n \t\t\t\tclose(cmd->out);\n-\t\t\treturn -ERR_RUN_COMMAND_PIPE;\n+fail_pipe:\n+\t\t\terror(\"cannot create pipe for %s: %s\",\n+\t\t\t\tcmd->argv[0], strerror(failed_errno));\n+\t\t\terrno = failed_errno;\n+\t\t\treturn -1;\n \t\t}\n \t\tcmd->err = fderr[0];\n \t}\n@@ -122,6 +130,9 @@ int start_command(struct child_process *cmd)\n \t\t\t\tstrerror(errno));\n \t\texit(127);\n \t}\n+\tif (cmd->pid < 0)\n+\t\terror(\"cannot fork() for %s: %s\", cmd->argv[0],\n+\t\t\tstrerror(failed_errno = errno));\n #else\n \tint s0 = -1, s1 = -1, s2 = -1;\t/* backups of stdin, stdout, stderr */\n \tconst char **sargv = cmd->argv;\n@@ -173,6 +184,9 @@ int start_command(struct child_process *cmd)\n \t}\n \n \tcmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);\n+\tif (cmd->pid < 0 && errno != ENOENT)\n+\t\terror(\"cannot spawn %s: %s\", cmd->argv[0],\n+\t\t\tstrerror(failed_errno = errno));\n \n \tif (cmd->env)\n \t\tfree_environ(env);\n@@ -189,7 +203,6 @@ int start_command(struct child_process *cmd)\n #endif\n \n \tif (cmd->pid < 0) {\n-\t\tint err = errno;\n \t\tif (need_in)\n \t\t\tclose_pair(fdin);\n \t\telse if (cmd->in)\n@@ -200,9 +213,8 @@ int start_command(struct child_process *cmd)\n \t\t\tclose(cmd->out);\n \t\tif (need_err)\n \t\t\tclose_pair(fderr);\n-\t\treturn err == ENOENT ?\n-\t\t\t-ERR_RUN_COMMAND_EXEC :\n-\t\t\t-ERR_RUN_COMMAND_FORK;\n+\t\terrno = failed_errno;\n+\t\treturn -1;\n \t}\n \n \tif (need_in)\n@@ -221,33 +233,41 @@ int start_command(struct child_process *cmd)\n \treturn 0;\n }\n \n-static int wait_or_whine(pid_t pid)\n+static int wait_or_whine(pid_t pid, const char *argv0)\n {\n-\tfor (;;) {\n-\t\tint status, code;\n-\t\tpid_t waiting = waitpid(pid, &status, 0);\n-\n-\t\tif (waiting < 0) {\n-\t\t\tif (errno == EINTR)\n-\t\t\t\tcontinue;\n-\t\t\terror(\"waitpid failed (%s)\", strerror(errno));\n-\t\t\treturn -ERR_RUN_COMMAND_WAITPID;\n-\t\t}\n-\t\tif (waiting != pid)\n-\t\t\treturn -ERR_RUN_COMMAND_WAITPID_WRONG_PID;\n-\t\tif (WIFSIGNALED(status))\n-\t\t\treturn -ERR_RUN_COMMAND_WAITPID_SIGNAL;\n-\n-\t\tif (!WIFEXITED(status))\n-\t\t\treturn -ERR_RUN_COMMAND_WAITPID_NOEXIT;\n+\tint status, code = -1;\n+\tpid_t waiting;\n+\tint failed_errno = 0;\n+\n+\twhile ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)\n+\t\t;\t/* nothing */\n+\n+\tif (waiting < 0) {\n+\t\tfailed_errno = errno;\n+\t\terror(\"waitpid for %s failed: %s\", argv0, strerror(errno));\n+\t} else if (waiting != pid) {\n+\t\terror(\"waitpid is confused (%s)\", argv0);\n+\t} else if (WIFSIGNALED(status)) {\n+\t\terror(\"%s died of signal\", argv0);\n+\t} else if (WIFEXITED(status)) {\n \t\tcode = WEXITSTATUS(status);\n-\t\treturn code == 127 ? -ERR_RUN_COMMAND_EXEC : code;\n+\t\t/*\n+\t\t * Convert special exit code when execvp failed.\n+\t\t */\n+\t\tif (code == 127) {\n+\t\t\tcode = -1;\n+\t\t\tfailed_errno = ENOENT;\n+\t\t}\n+\t} else {\n+\t\terror(\"waitpid is confused (%s)\", argv0);\n \t}\n+\terrno = failed_errno;\n+\treturn code;\n }\n \n int finish_command(struct child_process *cmd)\n {\n-\treturn wait_or_whine(cmd->pid);\n+\treturn wait_or_whine(cmd->pid, cmd->argv[0]);\n }\n \n int run_command(struct child_process *cmd)\n@@ -331,10 +351,7 @@ int start_async(struct async *async)\n int finish_async(struct async *async)\n {\n #ifndef __MINGW32__\n-\tint ret = 0;\n-\n-\tif (wait_or_whine(async->pid))\n-\t\tret = error(\"waitpid (async) failed\");\n+\tint ret = wait_or_whine(async->pid, \"child process\");\n #else\n \tDWORD ret = 0;\n \tif (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)\n@@ -378,15 +395,7 @@ int run_hook(const char *index_file, const char *name, ...)\n \t\thook.env = env;\n \t}\n \n-\tret = start_command(&hook);\n+\tret = run_command(&hook);\n \tfree(argv);\n-\tif (ret) {\n-\t\twarning(\"Could not spawn %s\", argv[0]);\n-\t\treturn ret;\n-\t}\n-\tret = finish_command(&hook);\n-\tif (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL)\n-\t\twarning(\"%s exited due to uncaught signal\", argv[0]);\n-\n \treturn ret;\n }\ndiff --git a/run-command.h b/run-command.h\nindex 0211e1d..ac6c09c 100644\n--- a/run-command.h\n+++ b/run-command.h\n@@ -1,16 +1,6 @@\n #ifndef RUN_COMMAND_H\n #define RUN_COMMAND_H\n \n-enum {\n-\tERR_RUN_COMMAND_FORK = 10000,\n-\tERR_RUN_COMMAND_EXEC,\n-\tERR_RUN_COMMAND_PIPE,\n-\tERR_RUN_COMMAND_WAITPID,\n-\tERR_RUN_COMMAND_WAITPID_WRONG_PID,\n-\tERR_RUN_COMMAND_WAITPID_SIGNAL,\n-\tERR_RUN_COMMAND_WAITPID_NOEXIT,\n-};\n-\n struct child_process {\n \tconst char **argv;\n \tpid_t pid;\ndiff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh\nindex f5102b9..82ca300 100755\n--- a/t/t5530-upload-pack-error.sh\n+++ b/t/t5530-upload-pack-error.sh\n@@ -53,7 +53,10 @@ test_expect_success 'upload-pack fails due to error in rev-list' '\n \t! echo \"0032want $(git rev-parse HEAD)\n 00000009done\n 0000\" | git upload-pack . > /dev/null 2> output.err &&\n-\tgrep \"waitpid (async) failed\" output.err\n+\t# pack-objects survived\n+\tgrep \"Total.*, reused\" output.err &&\n+\t# but there was an error, which must have been in rev-list\n+\tgrep \"bad tree object\" output.err\n '\n \n test_expect_success 'create empty repository' '\ndiff --git a/transport.c b/transport.c\nindex 501a77b..0885801 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -417,18 +417,8 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n \t\targv[argc++] = *refspec++;\n \targv[argc] = NULL;\n \terr = run_command_v_opt(argv, RUN_GIT_CMD);\n-\tswitch (err) {\n-\tcase -ERR_RUN_COMMAND_FORK:\n-\t\terror(\"unable to fork for %s\", argv[0]);\n-\tcase -ERR_RUN_COMMAND_EXEC:\n+\tif (err < 0 && errno == ENOENT)\n \t\terror(\"unable to exec %s\", argv[0]);\n-\t\tbreak;\n-\tcase -ERR_RUN_COMMAND_WAITPID:\n-\tcase -ERR_RUN_COMMAND_WAITPID_WRONG_PID:\n-\tcase -ERR_RUN_COMMAND_WAITPID_SIGNAL:\n-\tcase -ERR_RUN_COMMAND_WAITPID_NOEXIT:\n-\t\terror(\"%s died with strange error\", argv[0]);\n-\t}\n \treturn !!err;\n }\n \n-- \n1.6.3.17.g1665f\n"},{"id":"117443","messageId":"195a33e7de20a4b52df8cb8861998fbbbed0b311.1246734159.git.j6t@kdbg.org","threadId":"20024","inReplyTo":"ea2d8110ea70b8698bb3674ca4482db64053d841.1246734159.git.j6t@kdbg.org","subject":"[PATCH 5/7] run_command: encode deadly signal number in the return value","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-04T19:26:41Z","receivedAt":"2009-07-04T19:26:41Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"We now write the signal number in the error message if the program\nterminated by a signal. The negative return value is constructed such that\nafter truncation to 8 bits it looks like a POSIX shell's $?:\n\n   $ echo 0000 | { git upload-pack .; echo $? >&2; } | :\n   error: git-upload-pack died of signal 13\n   141\n\nPreviously, the exit code was 255 instead of 141.\n\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n run-command.c |    9 ++++++++-\n 1 files changed, 8 insertions(+), 1 deletions(-)\n\ndiff --git a/run-command.c b/run-command.c\nindex 4b3fda0..146a8ea 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -248,7 +248,14 @@ static int wait_or_whine(pid_t pid, const char *argv0)\n \t} else if (waiting != pid) {\n \t\terror(\"waitpid is confused (%s)\", argv0);\n \t} else if (WIFSIGNALED(status)) {\n-\t\terror(\"%s died of signal\", argv0);\n+\t\tcode = WTERMSIG(status);\n+\t\terror(\"%s died of signal %d\", argv0, code);\n+\t\t/*\n+\t\t * This return value is chosen so that code & 0xff\n+\t\t * mimics the exit code that a POSIX shell would report for\n+\t\t * a program that died from this signal.\n+\t\t */\n+\t\tcode -= 128;\n \t} else if (WIFEXITED(status)) {\n \t\tcode = WEXITSTATUS(status);\n \t\t/*\n-- \n1.6.3.17.g1665f\n"},{"id":"117447","messageId":"87ce2ffef09004ca19acd491b9374283f06c98c2.1246734159.git.j6t@kdbg.org","threadId":"20024","inReplyTo":"195a33e7de20a4b52df8cb8861998fbbbed0b311.1246734159.git.j6t@kdbg.org","subject":"[PATCH 6/7] run_command: report failure to execute the program, but optionally don't","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-04T19:26:42Z","receivedAt":"2009-07-04T19:26:42Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"In the case where a program was not found, it was still the task of the\ncaller to report an error to the user. Usually, this is an interesting case\nbut only few callers actually reported a specific error (though many call\nsites report a generic error message regardless of the cause).\n\nWith this change the error is reported by run_command, but since there is\none call site in git.c that does not want that, an option is added to\nstruct child_process, which is used to turn the error off.\n\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n builtin-receive-pack.c |    4 +---\n git.c                  |    2 +-\n run-command.c          |   12 ++++++++----\n run-command.h          |    2 ++\n transport.c            |    6 +-----\n 5 files changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin-receive-pack.c b/builtin-receive-pack.c\nindex 1dcdb1a..c85507b 100644\n--- a/builtin-receive-pack.c\n+++ b/builtin-receive-pack.c\n@@ -125,9 +125,7 @@ static const char post_receive_hook[] = \"hooks/post-receive\";\n \n static int run_status(int code, const char *cmd_name)\n {\n-\tif (code < 0 && errno == ENOENT)\n-\t\treturn error(\"execute of %s failed\", cmd_name);\n-\telse if (code > 0)\n+\tif (code > 0)\n \t\terror(\"%s exited with error code %d\", cmd_name, code);\n \treturn code;\n }\ndiff --git a/git.c b/git.c\nindex 2fb7093..4a977f5 100644\n--- a/git.c\n+++ b/git.c\n@@ -416,7 +416,7 @@ static void execv_dashed_external(const char **argv)\n \t * if we fail because the command is not found, it is\n \t * OK to return. Otherwise, we just pass along the status code.\n \t */\n-\tstatus = run_command_v_opt(argv, 0);\n+\tstatus = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE);\n \tif (status >= 0 || errno != ENOENT)\n \t\texit(status & 0xff);\n \ndiff --git a/run-command.c b/run-command.c\nindex 146a8ea..ddf3dd3 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -184,7 +184,7 @@ fail_pipe:\n \t}\n \n \tcmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);\n-\tif (cmd->pid < 0 && errno != ENOENT)\n+\tif (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))\n \t\terror(\"cannot spawn %s: %s\", cmd->argv[0],\n \t\t\tstrerror(failed_errno = errno));\n \n@@ -233,7 +233,7 @@ fail_pipe:\n \treturn 0;\n }\n \n-static int wait_or_whine(pid_t pid, const char *argv0)\n+static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)\n {\n \tint status, code = -1;\n \tpid_t waiting;\n@@ -264,6 +264,9 @@ static int wait_or_whine(pid_t pid, const char *argv0)\n \t\tif (code == 127) {\n \t\t\tcode = -1;\n \t\t\tfailed_errno = ENOENT;\n+\t\t\tif (!silent_exec_failure)\n+\t\t\t\terror(\"cannot run %s: %s\", argv0,\n+\t\t\t\t\tstrerror(ENOENT));\n \t\t}\n \t} else {\n \t\terror(\"waitpid is confused (%s)\", argv0);\n@@ -274,7 +277,7 @@ static int wait_or_whine(pid_t pid, const char *argv0)\n \n int finish_command(struct child_process *cmd)\n {\n-\treturn wait_or_whine(cmd->pid, cmd->argv[0]);\n+\treturn wait_or_whine(cmd->pid, cmd->argv[0], cmd->silent_exec_failure);\n }\n \n int run_command(struct child_process *cmd)\n@@ -294,6 +297,7 @@ static void prepare_run_command_v_opt(struct child_process *cmd,\n \tcmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;\n \tcmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;\n \tcmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;\n+\tcmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;\n }\n \n int run_command_v_opt(const char **argv, int opt)\n@@ -358,7 +362,7 @@ int start_async(struct async *async)\n int finish_async(struct async *async)\n {\n #ifndef __MINGW32__\n-\tint ret = wait_or_whine(async->pid, \"child process\");\n+\tint ret = wait_or_whine(async->pid, \"child process\", 0);\n #else\n \tDWORD ret = 0;\n \tif (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)\ndiff --git a/run-command.h b/run-command.h\nindex ac6c09c..0c00b25 100644\n--- a/run-command.h\n+++ b/run-command.h\n@@ -31,6 +31,7 @@ struct child_process {\n \tunsigned no_stdout:1;\n \tunsigned no_stderr:1;\n \tunsigned git_cmd:1; /* if this is to be git sub-command */\n+\tunsigned silent_exec_failure:1;\n \tunsigned stdout_to_stderr:1;\n \tvoid (*preexec_cb)(void);\n };\n@@ -44,6 +45,7 @@ extern int run_hook(const char *index_file, const char *name, ...);\n #define RUN_COMMAND_NO_STDIN 1\n #define RUN_GIT_CMD\t     2\t/*If this is to be git sub-command */\n #define RUN_COMMAND_STDOUT_TO_STDERR 4\n+#define RUN_SILENT_EXEC_FAILURE 8\n int run_command_v_opt(const char **argv, int opt);\n \n /*\ndiff --git a/transport.c b/transport.c\nindex 0885801..802ce7f 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -396,7 +396,6 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n {\n \tconst char **argv;\n \tint argc;\n-\tint err;\n \n \tif (flags & TRANSPORT_PUSH_MIRROR)\n \t\treturn error(\"http transport does not support mirror mode\");\n@@ -416,10 +415,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n \twhile (refspec_nr--)\n \t\targv[argc++] = *refspec++;\n \targv[argc] = NULL;\n-\terr = run_command_v_opt(argv, RUN_GIT_CMD);\n-\tif (err < 0 && errno == ENOENT)\n-\t\terror(\"unable to exec %s\", argv[0]);\n-\treturn !!err;\n+\treturn !!run_command_v_opt(argv, RUN_GIT_CMD);\n }\n \n static struct ref *get_refs_via_curl(struct transport *transport, int for_push)\n-- \n1.6.3.17.g1665f\n"},{"id":"117446","messageId":"bc993d449ea426dfdbf6feb76779d98944a8b29a.1246734159.git.j6t@kdbg.org","threadId":"20024","inReplyTo":"87ce2ffef09004ca19acd491b9374283f06c98c2.1246734159.git.j6t@kdbg.org","subject":"[PATCH/RFC 7/7] receive-pack: remove unnecessary run_status report","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-04T19:26:43Z","receivedAt":"2009-07-04T19:26:43Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"The function run_status was used to report failures after a hook was run.\nBy now, the only thing that the function itself reported was the exit code\nof the hook (if it was non-zero). But this is redundant because it can be\nexpected that the hook itself will have reported a suitable error.\n\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n builtin-receive-pack.c |   20 ++++----------------\n 1 files changed, 4 insertions(+), 16 deletions(-)\n\ndiff --git a/builtin-receive-pack.c b/builtin-receive-pack.c\nindex c85507b..b771fe9 100644\n--- a/builtin-receive-pack.c\n+++ b/builtin-receive-pack.c\n@@ -123,13 +123,6 @@ static struct command *commands;\n static const char pre_receive_hook[] = \"hooks/pre-receive\";\n static const char post_receive_hook[] = \"hooks/post-receive\";\n \n-static int run_status(int code, const char *cmd_name)\n-{\n-\tif (code > 0)\n-\t\terror(\"%s exited with error code %d\", cmd_name, code);\n-\treturn code;\n-}\n-\n static int run_receive_hook(const char *hook_name)\n {\n \tstatic char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];\n@@ -156,7 +149,7 @@ static int run_receive_hook(const char *hook_name)\n \n \tcode = start_command(&proc);\n \tif (code)\n-\t\treturn run_status(code, hook_name);\n+\t\treturn code;\n \tfor (cmd = commands; cmd; cmd = cmd->next) {\n \t\tif (!cmd->error_string) {\n \t\t\tsize_t n = snprintf(buf, sizeof(buf), \"%s %s %s\\n\",\n@@ -168,7 +161,7 @@ static int run_receive_hook(const char *hook_name)\n \t\t}\n \t}\n \tclose(proc.in);\n-\treturn run_status(finish_command(&proc), hook_name);\n+\treturn finish_command(&proc);\n }\n \n static int run_update_hook(struct command *cmd)\n@@ -185,9 +178,8 @@ static int run_update_hook(struct command *cmd)\n \targv[3] = sha1_to_hex(cmd->new_sha1);\n \targv[4] = NULL;\n \n-\treturn run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |\n-\t\t\t\t\tRUN_COMMAND_STDOUT_TO_STDERR),\n-\t\t\tupdate_hook);\n+\treturn run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |\n+\t\t\t\t\tRUN_COMMAND_STDOUT_TO_STDERR);\n }\n \n static int is_ref_checked_out(const char *ref)\n@@ -401,7 +393,6 @@ static void run_update_post_hook(struct command *cmd)\n \targv[argc] = NULL;\n \tstatus = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN\n \t\t\t| RUN_COMMAND_STDOUT_TO_STDERR);\n-\trun_status(status, update_post_hook);\n }\n \n static void execute_commands(const char *unpacker_error)\n@@ -519,7 +510,6 @@ static const char *unpack(void)\n \t\tcode = run_command_v_opt(unpacker, RUN_GIT_CMD);\n \t\tif (!code)\n \t\t\treturn NULL;\n-\t\trun_status(code, unpacker[0]);\n \t\treturn \"unpack-objects abnormal exit\";\n \t} else {\n \t\tconst char *keeper[7];\n@@ -545,7 +535,6 @@ static const char *unpack(void)\n \t\tip.git_cmd = 1;\n \t\tstatus = start_command(&ip);\n \t\tif (status) {\n-\t\t\trun_status(status, keeper[0]);\n \t\t\treturn \"index-pack fork failed\";\n \t\t}\n \t\tpack_lockfile = index_pack_lockfile(ip.out);\n@@ -555,7 +544,6 @@ static const char *unpack(void)\n \t\t\treprepare_packed_git();\n \t\t\treturn NULL;\n \t\t}\n-\t\trun_status(status, keeper[0]);\n \t\treturn \"index-pack abnormal exit\";\n \t}\n }\n-- \n1.6.3.17.g1665f\n"},{"id":"117464","messageId":"200907052057.46200.j6t@kdbg.org","threadId":"20024","inReplyTo":"b73cf4b4cd09f4225098e71182044f64e12380aa.1246734159.git.j6t@kdbg.org","subject":"[Replacement PATCH 1/7] MinGW: truncate exit()'s argument to lowest 8 bits","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-05T18:57:46Z","receivedAt":"2009-07-05T18:57:46Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"For some reason, MinGW's bash cannot reliably detect failure of the child\nprocess if a negative value is passed to exit(). This fixes it by\ntruncating the exit code in all calls of exit().\n\nThis issue was worked around in run_builtin() of git.c (2488df84 builtin\nrun_command: do not exit with -1, 2007-11-15). This workaround is no longer\nnecessary and is reverted.\n\nSuggested-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n compat/mingw.h |    2 ++\n git.c          |    2 +-\n 2 files changed, 3 insertions(+), 1 deletions(-)\n\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 4f7ba4c..c1859c5 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -92,6 +92,8 @@ static inline int fcntl(int fd, int cmd, long arg)\n \terrno = EINVAL;\n \treturn -1;\n }\n+/* bash cannot reliably detect negative return codes as failure */\n+#define exit(code) exit((code) & 0xff)\n \n /*\n  * simple adaptors\ndiff --git a/git.c b/git.c\nindex f4d53f4..65ed733 100644\n--- a/git.c\n+++ b/git.c\n@@ -245,7 +245,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \n \tstatus = p->fn(argc, argv, prefix);\n \tif (status)\n-\t\treturn status & 0xff;\n+\t\treturn status;\n \n \t/* Somebody closed stdout? */\n \tif (fstat(fileno(stdout), &st))\n-- \n1.6.3.3.393.g6b649\n"},{"id":"117465","messageId":"200907052101.13741.j6t@kdbg.org","threadId":"20024","inReplyTo":"ea2d8110ea70b8698bb3674ca4482db64053d841.1246734159.git.j6t@kdbg.org","subject":"Re: [PATCH 4/7] run_command: report system call errors instead of returning error codes","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-07-05T19:01:13Z","receivedAt":"2009-07-05T19:01:13Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Samstag, 4. Juli 2009, Johannes Sixt wrote:\n> +\tif (status >= 0 || errno != ENOENT)\n> +\t\texit(status & 0xff);\n\nWith my replacement patch 1/7 this '& 0xff' is no longer necessary. Would you\nkindly squash this in?\n\n-- Hannes\n\ndiff --git a/git.c b/git.c\n--- a/git.c\n+++ b/git.c\n@@ -418,7 +418,7 @@ static void execv_dashed_external(const char **argv)\n \t */\n \tstatus = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE);\n \tif (status >= 0 || errno != ENOENT)\n-\t\texit(status & 0xff);\n+\t\texit(status);\n \n \targv[0] = tmp;\n \n"},{"id":"117466","messageId":"7v3a9bj61m.fsf@alter.siamese.dyndns.org","threadId":"20024","inReplyTo":"200907052101.13741.j6t@kdbg.org","subject":"Re: [PATCH 4/7] run_command: report system call errors instead of returning error codes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-05T19:14:45Z","receivedAt":"2009-07-05T19:14:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j6t@kdbg.org> writes:\n\n> On Samstag, 4. Juli 2009, Johannes Sixt wrote:\n>> +\tif (status >= 0 || errno != ENOENT)\n>> +\t\texit(status & 0xff);\n>\n> With my replacement patch 1/7 this '& 0xff' is no longer necessary. Would you\n> kindly squash this in?\n\nSounds sensible.  Thanks.\n"},{"id":"117492","messageId":"4A51A9BF.5050104@viscovery.net","threadId":"20024","inReplyTo":"ea2d8110ea70b8698bb3674ca4482db64053d841.1246734159.git.j6t@kdbg.org","subject":"Re: [PATCH 4/7] run_command: report system call errors instead of returning error codes","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-07-06T07:37:35Z","receivedAt":"2009-07-06T07:37:35Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Johannes Sixt schrieb:\n>  \tcmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);\n> +\tif (cmd->pid < 0 && errno != ENOENT)\n> +\t\terror(\"cannot spawn %s: %s\", cmd->argv[0],\n> +\t\t\tstrerror(failed_errno = errno));\n>  \n>  \tif (cmd->env)\n>  \t\tfree_environ(env);\n> @@ -189,7 +203,6 @@ int start_command(struct child_process *cmd)\n>  #endif\n>  \n>  \tif (cmd->pid < 0) {\n> -\t\tint err = errno;\n>  \t\tif (need_in)\n>  \t\t\tclose_pair(fdin);\n>  \t\telse if (cmd->in)\n> @@ -200,9 +213,8 @@ int start_command(struct child_process *cmd)\n>  \t\t\tclose(cmd->out);\n>  \t\tif (need_err)\n>  \t\t\tclose_pair(fderr);\n> -\t\treturn err == ENOENT ?\n> -\t\t\t-ERR_RUN_COMMAND_EXEC :\n> -\t\t\t-ERR_RUN_COMMAND_FORK;\n> +\t\terrno = failed_errno;\n> +\t\treturn -1;\n>  \t}\n\nSorry to bother you once again. 'gcc -O2' correctly points out that\nfailed_errno could be used uninitialized (MinGW code path only).\nWould you please squash this in?\n\n-- Hannes\n\ndiff --git a/run-command.c b/run-command.c\n--- a/run-command.c\n+++ b/run-command.c\n@@ -184,9 +184,9 @@ fail_pipe:\n \t}\n\n \tcmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);\n+\tfailed_errno = errno;\n \tif (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))\n-\t\terror(\"cannot spawn %s: %s\", cmd->argv[0],\n-\t\t\tstrerror(failed_errno = errno));\n+\t\terror(\"cannot spawn %s: %s\", cmd->argv[0], strerror(errno));\n\n \tif (cmd->env)\n \t\tfree_environ(env);\n"}]}