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
|
||||
* inherits no concurrent siblings — system() spawns a fresh /bin/sh -c.
|
||||
* 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
|
||||
spawn_build(const char *bin, const char *cwd, struct buildjob *j)
|
||||
{
|
||||
snprintf(j->workdir, sizeof j->workdir, "/tmp/wwsr_%d_%s",
|
||||
getpid(), j->tool);
|
||||
char setup[256];
|
||||
snprintf(setup, sizeof setup, "rm -rf %s && mkdir -p %s",
|
||||
j->workdir, j->workdir);
|
||||
char setup[4096];
|
||||
snprintf(setup, sizeof setup, "rm -rf %s && mkdir -p %s && cp %s/%s %s/build.ww",
|
||||
j->workdir, j->workdir, cwd, j->src_rel, j->workdir);
|
||||
if (runwait(setup) != 0) return -1;
|
||||
|
||||
char cmd[4096];
|
||||
@@ -98,15 +104,15 @@ spawn_build(const char *bin, const char *cwd, struct buildjob *j)
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"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/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,
|
||||
cwd, cwd, cwd, cwd, cwd, j->src_rel, j->workdir);
|
||||
cwd, cwd, cwd, cwd, j->workdir);
|
||||
} else {
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"cd %s && timeout 180 %s/ww_ww build "
|
||||
"-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",
|
||||
j->workdir, bin, cwd, cwd, cwd, cwd, cwd, j->src_rel, j->workdir);
|
||||
"-I %s/selfhost/cmd/wcc build.ww >/dev/null 2>%s/build.err",
|
||||
j->workdir, bin, cwd, cwd, cwd, cwd, j->workdir);
|
||||
}
|
||||
|
||||
pid_t p = fork();
|
||||
@@ -146,7 +152,7 @@ collect_build(const char *bin, struct buildjob *j)
|
||||
rc = -1;
|
||||
} else {
|
||||
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);
|
||||
rc = slurp_eq(rebuilt, canonical);
|
||||
if (rc != 0) {
|
||||
|
||||
Reference in New Issue
Block a user