diff options
author | Ron Yorston <rmy@pobox.com> | 2023-09-12 14:03:26 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-09-12 15:01:06 +0100 |
commit | 504f373c8d4447a4801a74887f99f0dfa809f53e (patch) | |
tree | b96d61abd47657a60f8e1a194e31b1019f2a2be4 | |
parent | faf0d38e40e099eebccac4013ab2692e545f612e (diff) | |
download | busybox-w32-504f373c8d4447a4801a74887f99f0dfa809f53e.tar.gz busybox-w32-504f373c8d4447a4801a74887f99f0dfa809f53e.tar.bz2 busybox-w32-504f373c8d4447a4801a74887f99f0dfa809f53e.zip |
make: return non-zero exit status when a command fails
When a build command returned a non-zero exit status 'make'
reported a warning and returned an exit code of zero.
This was due to the misuse of the status returned by system(3).
As the man page says:
the return value is a "wait status" that can be examined using
the macros described in waitpid(2). (i.e., WIFEXITED(),
WEXITSTATUS(), and so on).
Use the error() function to correctly report the problem on stderr
and return an exit status of 2.
Some additional changes in the same area:
- When a target is removed report the diagnostic on stderr, as
required by POSIX.
- When a build command receives a signal GNU make removes the target.
bmake doesn't and it isn't required by POSIX. Implement this as an
extension.
- Expand the error message when a build command fails so it includes
the exit status or signal number, as obtained from the value
returned by system(3).
- Alter the WIN32 implementation of system(3) to handle exit codes
which represent termination as if by a signal.
Adds 200-240 bytes.
(GitHub issue #354)
-rw-r--r-- | miscutils/make.c | 45 | ||||
-rwxr-xr-x | testsuite/make.tests | 8 | ||||
-rw-r--r-- | win32/system.c | 5 |
3 files changed, 48 insertions, 10 deletions
diff --git a/miscutils/make.c b/miscutils/make.c index d554a5f7f..8feec1202 100644 --- a/miscutils/make.c +++ b/miscutils/make.c | |||
@@ -293,6 +293,19 @@ vwarning(FILE *stream, const char *msg, va_list list) | |||
293 | } | 293 | } |
294 | 294 | ||
295 | /* | 295 | /* |
296 | * Diagnostic handler. Print message to standard error. | ||
297 | */ | ||
298 | static void | ||
299 | diagnostic(const char *msg, ...) | ||
300 | { | ||
301 | va_list list; | ||
302 | |||
303 | va_start(list, msg); | ||
304 | vwarning(stderr, msg, list); | ||
305 | va_end(list); | ||
306 | } | ||
307 | |||
308 | /* | ||
296 | * Error handler. Print message and exit. | 309 | * Error handler. Print message and exit. |
297 | */ | 310 | */ |
298 | static void error(const char *msg, ...) NORETURN; | 311 | static void error(const char *msg, ...) NORETURN; |
@@ -2111,7 +2124,7 @@ remove_target(void) | |||
2111 | if (!dryrun && !print && !precious && | 2124 | if (!dryrun && !print && !precious && |
2112 | target && !(target->n_flag & (N_PRECIOUS | N_PHONY)) && | 2125 | target && !(target->n_flag & (N_PRECIOUS | N_PHONY)) && |
2113 | unlink(target->n_name) == 0) { | 2126 | unlink(target->n_name) == 0) { |
2114 | warning("'%s' removed", target->n_name); | 2127 | diagnostic("'%s' removed", target->n_name); |
2115 | } | 2128 | } |
2116 | } | 2129 | } |
2117 | 2130 | ||
@@ -2164,23 +2177,35 @@ docmds(struct name *np, struct cmd *cp) | |||
2164 | 2177 | ||
2165 | target = np; | 2178 | target = np; |
2166 | status = system(cmd); | 2179 | status = system(cmd); |
2167 | target = NULL; | ||
2168 | // If this command was being run to create an include file | 2180 | // If this command was being run to create an include file |
2169 | // or bring it up-to-date errors should be ignored and a | 2181 | // or bring it up-to-date errors should be ignored and a |
2170 | // failure status returned. | 2182 | // failure status returned. |
2171 | if (status == -1 && !doinclude) { | 2183 | if (status == -1 && !doinclude) { |
2172 | error("couldn't execute '%s'", q); | 2184 | error("couldn't execute '%s'", q); |
2173 | } else if (status != 0 && !signore) { | 2185 | } else if (status != 0 && !signore) { |
2174 | if (!doinclude) | 2186 | if (!posix && WIFSIGNALED(status)) |
2175 | warning("failed to build '%s'", np->n_name); | ||
2176 | #if !ENABLE_PLATFORM_MINGW32 | ||
2177 | if (status == SIGINT || status == SIGQUIT) | ||
2178 | #endif | ||
2179 | remove_target(); | 2187 | remove_target(); |
2180 | if (errcont || doinclude) | 2188 | if (errcont || doinclude) { |
2189 | warning("failed to build '%s'", np->n_name); | ||
2181 | estat |= MAKE_FAILURE; | 2190 | estat |= MAKE_FAILURE; |
2182 | else | 2191 | } else { |
2183 | exit(status); | 2192 | const char *err_type = NULL; |
2193 | int err_value; | ||
2194 | |||
2195 | if (WIFEXITED(status)) { | ||
2196 | err_type = "exit"; | ||
2197 | err_value = WEXITSTATUS(status); | ||
2198 | } else if (WIFSIGNALED(status)) { | ||
2199 | err_type = "signal"; | ||
2200 | err_value = WTERMSIG(status); | ||
2201 | } | ||
2202 | |||
2203 | if (err_type) | ||
2204 | error("failed to build '%s' %s %d", np->n_name, | ||
2205 | err_type, err_value); | ||
2206 | else | ||
2207 | error("failed to build '%s'", np->n_name); | ||
2208 | } | ||
2184 | } | 2209 | } |
2185 | } | 2210 | } |
2186 | if (sdomake || dryrun || dotouch) | 2211 | if (sdomake || dryrun || dotouch) |
diff --git a/testsuite/make.tests b/testsuite/make.tests index b53b4a2ea..60bb78406 100755 --- a/testsuite/make.tests +++ b/testsuite/make.tests | |||
@@ -86,6 +86,14 @@ test.k: | |||
86 | ' | 86 | ' |
87 | cd .. || exit 1; rm -rf make.tempdir 2>/dev/null | 87 | cd .. || exit 1; rm -rf make.tempdir 2>/dev/null |
88 | 88 | ||
89 | # There was a bug where the failure of a build command didn't result | ||
90 | # in make returning a non-zero exit status. | ||
91 | testing "make return error if command fails" \ | ||
92 | "make -f - >/dev/null 2>&1; echo \$?" "2\n" "" ' | ||
93 | target: | ||
94 | @exit 42 | ||
95 | ' | ||
96 | |||
89 | # A macro created using ::= remembers it's of type immediate-expansion. | 97 | # A macro created using ::= remembers it's of type immediate-expansion. |
90 | # Immediate expansion also occurs when += is used to append to such a macro. | 98 | # Immediate expansion also occurs when += is used to append to such a macro. |
91 | testing "make appending to immediate-expansion macro" \ | 99 | testing "make appending to immediate-expansion macro" \ |
diff --git a/win32/system.c b/win32/system.c index 44a47f861..00b594242 100644 --- a/win32/system.c +++ b/win32/system.c | |||
@@ -6,6 +6,7 @@ int mingw_system(const char *cmd) | |||
6 | intptr_t proc; | 6 | intptr_t proc; |
7 | HANDLE h; | 7 | HANDLE h; |
8 | DWORD ret = 0; | 8 | DWORD ret = 0; |
9 | int sig; | ||
9 | 10 | ||
10 | if (cmd == NULL) | 11 | if (cmd == NULL) |
11 | return 1; | 12 | return 1; |
@@ -18,5 +19,9 @@ int mingw_system(const char *cmd) | |||
18 | GetExitCodeProcess(h, &ret); | 19 | GetExitCodeProcess(h, &ret); |
19 | CloseHandle(h); | 20 | CloseHandle(h); |
20 | 21 | ||
22 | // Was process terminated as if by a signal? | ||
23 | sig = ret >> 24; | ||
24 | if (sig != 0 && ret == sig << 24 && is_valid_signal(sig)) | ||
25 | return sig; | ||
21 | return ret << 8; | 26 | return ret << 8; |
22 | } | 27 | } |