From 05769ca009e630c1989f29ca8cb9d0ec4cf2a8d8 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sat, 4 Aug 2018 19:07:59 -0400 Subject: [PATCH] [SV 54233] Preserve higher command_state values on also_make targets. If multiple pattern rules have the same pattern as also-make targets and we attempt to run them at the same time, we might downgrade the command state from 'running' to 'deps_running'; this will prevent that also_make from being considered complete causing make to wait forever for it to finish. Ensure that set_command_state never downgrades the state of a target. * src/file.c (set_command_state): Don't downgrade command_state. * src/filedef.h (struct file): Document the order prerequisite. * test/scripts/features/patternrules: Test the behavior. --- src/file.c | 7 +++++-- src/filedef.h | 2 +- tests/scripts/features/patternrules | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/file.c b/src/file.c index 4835e4f8..925ce8d8 100644 --- a/src/file.c +++ b/src/file.c @@ -788,7 +788,9 @@ snap_deps (void) #endif } -/* Set the 'command_state' member of FILE and all its 'also_make's. */ +/* Set the 'command_state' member of FILE and all its 'also_make's. + Don't decrease the state of also_make's (e.g., don't downgrade a 'running' + also_make to a 'deps_running' also_make). */ void set_command_state (struct file *file, enum cmd_state state) @@ -798,7 +800,8 @@ set_command_state (struct file *file, enum cmd_state state) file->command_state = state; for (d = file->also_make; d != 0; d = d->next) - d->file->command_state = state; + if (state > d->file->command_state) + d->file->command_state = state; } /* Convert an external file timestamp to internal form. */ diff --git a/src/filedef.h b/src/filedef.h index 8af562a1..9d4b816f 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -68,7 +68,7 @@ struct file us_question, /* Needs to be updated (-q is is set). */ us_failed /* Update failed. */ } update_status ENUM_BITFIELD (2); - enum cmd_state /* State of the commands. */ + enum cmd_state /* State of commands. ORDER IS IMPORTANT! */ { cs_not_started = 0, /* Not yet started. Must be 0! */ cs_deps_running, /* Dep commands running. */ diff --git a/tests/scripts/features/patternrules b/tests/scripts/features/patternrules index f76724eb..177bb32c 100644 --- a/tests/scripts/features/patternrules +++ b/tests/scripts/features/patternrules @@ -220,6 +220,22 @@ all: foo.x foo-mt.x 1; +# Test pattern rules building the same targets +# See SV 54233. Rely on our standard test timeout to break the loop + +touch('a.c'); + +run_make_test(q! +all: a.elf a.dbg + +%.elf %.lnk: %.c ; : $*.elf $*.lnk + +%.elf %.dbg: %.lnk ; : $*.elf $*.dbg +!, + '-j2', ": a.elf a.lnk\n: a.elf a.dbg\n"); + +unlink('a.c'); + # This tells the test driver that the perl test script executed properly. 1;