test/wcc/995_self_rebuild: stage source in workdir to avoid main.s race
ww_ww build writes its intermediates (.combined.ww/.s/.o/binary)
next to the source path. When 995 invoked `ww_ww build /abs/path/
selfhost/cmd/wwdump/main.ww` in parallel with 991/992/994 (which
read selfhost/cmd/<tool>/main.s as a fixture), the build mid-wrote
main.s and the fixture-reading test saw a partial 520B view of the
1.4MB file → "C 1422712 vs ww 520 bytes" assembler-byte-diff fail.
The race was latent pre-31594e4 too: parallel test/run + serial
995 always finished 995 last (3min wall), so 991 was already done
by the time 995's wwdump build wrote main.s. Internal-parallel 995
finishes in 1m47, opening the window.
Fix: cp the source to <workdir>/build.ww before invoking ww_ww,
build from build.ww. Driver writes intermediates as build.{combined.ww,
s,o} and binary `build` in workdir; canonical selfhost/cmd/<tool>/
main.* are never touched by 995. Imports still resolve via -I, but
those paths are read-only fixtures.
Verified 3 consecutive `make test` runs 132/132 (4:18, 3:22, 3:16).
This commit is contained in:
@@ -82,15 +82,21 @@ struct buildjob {
|
|||||||
/* Fork a child that runs the `ww_ww build` for this tool. The child
|
/* Fork a child that runs the `ww_ww build` for this tool. The child
|
||||||
* inherits no concurrent siblings — system() spawns a fresh /bin/sh -c.
|
* inherits no concurrent siblings — system() spawns a fresh /bin/sh -c.
|
||||||
* stderr lands in <workdir>/build.err so concurrent builds don't merge
|
* stderr lands in <workdir>/build.err so concurrent builds don't merge
|
||||||
* their diagnostics. */
|
* their diagnostics.
|
||||||
|
*
|
||||||
|
* The source is staged at <workdir>/build.ww before the build so the
|
||||||
|
* driver writes its .combined.ww/.s/.o intermediates inside workdir —
|
||||||
|
* not next to the canonical selfhost/cmd/<tool>/main.ww, where 991/992/
|
||||||
|
* 994 read main.s as a fixture. Without staging, parallel test/run sees
|
||||||
|
* 991 race against 995's wwdump-build mid-write of main.s. */
|
||||||
static int
|
static int
|
||||||
spawn_build(const char *bin, const char *cwd, struct buildjob *j)
|
spawn_build(const char *bin, const char *cwd, struct buildjob *j)
|
||||||
{
|
{
|
||||||
snprintf(j->workdir, sizeof j->workdir, "/tmp/wwsr_%d_%s",
|
snprintf(j->workdir, sizeof j->workdir, "/tmp/wwsr_%d_%s",
|
||||||
getpid(), j->tool);
|
getpid(), j->tool);
|
||||||
char setup[256];
|
char setup[4096];
|
||||||
snprintf(setup, sizeof setup, "rm -rf %s && mkdir -p %s",
|
snprintf(setup, sizeof setup, "rm -rf %s && mkdir -p %s && cp %s/%s %s/build.ww",
|
||||||
j->workdir, j->workdir);
|
j->workdir, j->workdir, cwd, j->src_rel, j->workdir);
|
||||||
if (runwait(setup) != 0) return -1;
|
if (runwait(setup) != 0) return -1;
|
||||||
|
|
||||||
char cmd[4096];
|
char cmd[4096];
|
||||||
@@ -98,15 +104,15 @@ spawn_build(const char *bin, const char *cwd, struct buildjob *j)
|
|||||||
snprintf(cmd, sizeof cmd,
|
snprintf(cmd, sizeof cmd,
|
||||||
"cd %s && timeout 180 %s/ww_ww build -I %s/%s "
|
"cd %s && timeout 180 %s/ww_ww build -I %s/%s "
|
||||||
"-I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse "
|
"-I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse "
|
||||||
"-I %s/selfhost/cmd/wcc %s/%s >/dev/null 2>%s/build.err",
|
"-I %s/selfhost/cmd/wcc build.ww >/dev/null 2>%s/build.err",
|
||||||
j->workdir, bin, cwd, j->inc_local,
|
j->workdir, bin, cwd, j->inc_local,
|
||||||
cwd, cwd, cwd, cwd, cwd, j->src_rel, j->workdir);
|
cwd, cwd, cwd, cwd, j->workdir);
|
||||||
} else {
|
} else {
|
||||||
snprintf(cmd, sizeof cmd,
|
snprintf(cmd, sizeof cmd,
|
||||||
"cd %s && timeout 180 %s/ww_ww build "
|
"cd %s && timeout 180 %s/ww_ww build "
|
||||||
"-I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse "
|
"-I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse "
|
||||||
"-I %s/selfhost/cmd/wcc %s/%s >/dev/null 2>%s/build.err",
|
"-I %s/selfhost/cmd/wcc build.ww >/dev/null 2>%s/build.err",
|
||||||
j->workdir, bin, cwd, cwd, cwd, cwd, cwd, j->src_rel, j->workdir);
|
j->workdir, bin, cwd, cwd, cwd, cwd, j->workdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t p = fork();
|
pid_t p = fork();
|
||||||
@@ -146,7 +152,7 @@ collect_build(const char *bin, struct buildjob *j)
|
|||||||
rc = -1;
|
rc = -1;
|
||||||
} else {
|
} else {
|
||||||
char rebuilt[256], canonical[256];
|
char rebuilt[256], canonical[256];
|
||||||
snprintf(rebuilt, sizeof rebuilt, "%s/main", j->workdir);
|
snprintf(rebuilt, sizeof rebuilt, "%s/build", j->workdir);
|
||||||
snprintf(canonical, sizeof canonical, "%s/%s_ww", bin, j->tool);
|
snprintf(canonical, sizeof canonical, "%s/%s_ww", bin, j->tool);
|
||||||
rc = slurp_eq(rebuilt, canonical);
|
rc = slurp_eq(rebuilt, canonical);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user