diff --git a/job.c b/job.c index bbc304ad..45a433f1 100644 --- a/job.c +++ b/job.c @@ -819,8 +819,6 @@ reap_children (int block, int err) break; } - child_failed = exit_sig != 0 || exit_code != 0; - /* Search for a child matching the deceased one. */ lastc = 0; for (c = children; c != 0; lastc = c, c = c->next) @@ -832,6 +830,15 @@ reap_children (int block, int err) Ignore it; it was inherited from our invoker. */ continue; + /* Determine the failure status: 0 for success, 1 for updating target in + question mode, 2 for anything else. */ + if (exit_sig == 0 && exit_code == 0) + child_failed = MAKE_SUCCESS; + else if (exit_sig == 0 && exit_code == 1 && question_flag && c->recursive) + child_failed = MAKE_TROUBLE; + else + child_failed = MAKE_FAILURE; + DB (DB_JOBS, (child_failed ? _("Reaping losing child %p PID %s %s\n") : _("Reaping winning child %p PID %s %s\n"), @@ -867,10 +874,10 @@ reap_children (int block, int err) delete non-precious targets, and abort. */ static int delete_on_error = -1; - if (!dontcare) + if (!dontcare && child_failed == MAKE_FAILURE) child_error (c, exit_code, exit_sig, coredump, 0); - c->file->update_status = us_failed; + c->file->update_status = child_failed == MAKE_FAILURE ? us_failed : us_question; if (delete_on_error == -1) { struct file *f = lookup_file (".DELETE_ON_ERROR"); @@ -982,7 +989,7 @@ reap_children (int block, int err) if (!err && child_failed && !dontcare && !keep_going_flag && /* fatal_error_signal will die with the right signal. */ !handling_fatal_signal) - die (MAKE_FAILURE); + die (child_failed); /* Only block for one child. */ block = 0; @@ -1188,14 +1195,15 @@ start_job_command (struct child *child) ++p; } + child->recursive = ((flags & COMMANDS_RECURSE) != 0); + /* Update the file's command flags with any new ones we found. We only keep the COMMANDS_RECURSE setting. Even this isn't 100% correct; we are now marking more commands recursive than should be in the case of multiline define/endef scripts where only one line is marked "+". In order to really fix this, we'll have to keep a lines_flags for every actual line, after expansion. */ - child->file->cmds->lines_flags[child->command_line - 1] - |= flags & COMMANDS_RECURSE; + child->file->cmds->lines_flags[child->command_line - 1] |= flags & COMMANDS_RECURSE; /* POSIX requires that a recipe prefix after a backslash-newline should be ignored. Remove it now so the output is correct. */ diff --git a/job.h b/job.h index 0243cddc..0beff738 100644 --- a/job.h +++ b/job.h @@ -109,6 +109,7 @@ struct child unsigned int noerror:1; /* Nonzero if commands contained a '-'. */ unsigned int good_stdin:1; /* Nonzero if this child has a good stdin. */ unsigned int deleted:1; /* Nonzero if targets have been deleted. */ + unsigned int recursive:1; /* Nonzero for recursive command ('+' etc.) */ unsigned int dontcare:1; /* Saved dontcare flag. */ }; diff --git a/tests/scripts/options/dash-q b/tests/scripts/options/dash-q index 194588d9..e67b55d4 100644 --- a/tests/scripts/options/dash-q +++ b/tests/scripts/options/dash-q @@ -74,4 +74,13 @@ build-y: build-x ', '-q build-y', "#MAKE#: *** No rule to make target 'build-stamp-2', needed by 'build-arch'. Stop.\n", 512); +# TEST 9 : Savannah bug # 47151 +# Make sure we exit with 1 when invoking a recursive make +run_make_test(' +foo: bar ; echo foo +bar: ; @$(MAKE) -f #MAKEFILE# baz +baz: ; echo baz +', + '-q foo', '', 256); + 1;