ww: invalidate partial package commits
This commit is contained in:
@@ -5093,6 +5093,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
return 1;
|
||||
};
|
||||
let anyfailed: bool = false;
|
||||
let commitopen: bool = false;
|
||||
let commitintegrityfailed: bool = false;
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
if (g.pkg[products[producti].root].failed) { anyfailed = true; };
|
||||
@@ -5139,6 +5141,12 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
if (sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew) < 0) {
|
||||
if (warm) {
|
||||
let unitrr: i32 = os.remove(pathstr(unitf));
|
||||
if (unitrr != 0 && unitrr != -2) {
|
||||
commitintegrityfailed = true;
|
||||
};
|
||||
};
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
oi += 1;
|
||||
@@ -5147,6 +5155,12 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
if (sepcomposeunit(g, pi, cu) < 0) {
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
if (warm) {
|
||||
let unitrr: i32 = os.remove(pathstr(unitf));
|
||||
if (unitrr != 0 && unitrr != -2) {
|
||||
commitintegrityfailed = true;
|
||||
};
|
||||
};
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
oi += 1;
|
||||
@@ -5162,7 +5176,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
let fresh: bool = false;
|
||||
if (warm) {
|
||||
if (!staleall && !depschanged) {
|
||||
if (!staleall && !depschanged && !commitintegrityfailed) {
|
||||
fresh = fileequal(unitnew, unitf);
|
||||
if (fresh) { fresh = fileisreg(asmf); };
|
||||
if (fresh) { fresh = fileisreg(wwi); };
|
||||
@@ -5190,6 +5204,22 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
oi += 1;
|
||||
continue;
|
||||
};
|
||||
// Once an action is not reusable, its old unit must not vouch for
|
||||
// artifacts after a later producer or commit failure. This also makes a
|
||||
// failed importer retry after a dependency committed a changed export.
|
||||
if (warm) {
|
||||
let unitrr: i32 = os.remove(pathstr(unitf));
|
||||
if (unitrr != 0 && unitrr != -2) {
|
||||
cerrpath("ww: cannot invalidate package unit ", unitf, "\n");
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
commitintegrityfailed = true;
|
||||
oi += 1;
|
||||
continue;
|
||||
};
|
||||
};
|
||||
{
|
||||
let rawtest: bool = (istest != 0) && g.pkg[pi].root
|
||||
&& g.pkg[pi].isdir == 0;
|
||||
@@ -5378,9 +5408,23 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
continue;
|
||||
};
|
||||
};
|
||||
// Commit order: artifacts before the unit that vouches for
|
||||
// them, unit strictly last.
|
||||
// Commit order: artifacts before the unit that vouches for them, unit
|
||||
// strictly last. Remove the workdir identity before the first artifact
|
||||
// rename; failure is a pre-commit rejection with old artifacts intact.
|
||||
if (warm) {
|
||||
if (!commitopen) {
|
||||
let stamprr: i32 = os.remove(pathstr(stampf));
|
||||
if (stamprr != 0 && stamprr != -2) {
|
||||
cerr("ww: cannot invalidate package workdir\n");
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
oi += 1;
|
||||
continue;
|
||||
};
|
||||
commitopen = true;
|
||||
};
|
||||
let bad: bool = false;
|
||||
if (os.rename(pathstr(wwinew), pathstr(wwi)) != 0) {
|
||||
bad = true;
|
||||
@@ -5418,6 +5462,11 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
// A failed rename sequence may already have replaced the
|
||||
// interface or another artifact. The stamp is already absent;
|
||||
// invalidate all vouchers and force later actions through tools.
|
||||
commitintegrityfailed = true;
|
||||
invalidateworkdirunits(scratch);
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
oi += 1;
|
||||
@@ -5427,9 +5476,10 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
oi += 1;
|
||||
};
|
||||
// A stale pass removed every old unit voucher before compiling. Current
|
||||
// successful units remain safe to vouch for when a sibling root fails;
|
||||
// a killed pass retains the old identity and invalidates again next time.
|
||||
if (warm) {
|
||||
// successful units remain safe when a sibling compiler rejects. A partial
|
||||
// artifact commit invalidates all vouchers and suppresses the workdir
|
||||
// identity so the next pass starts stale.
|
||||
if (warm && !commitintegrityfailed) {
|
||||
let sametool: bool = fileequal(toolw, selfpath);
|
||||
if (sepfatalallocation) { return 1; };
|
||||
if (!sametool) {
|
||||
@@ -5456,7 +5506,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
};
|
||||
};
|
||||
if (!stampok) {
|
||||
if (!stampok || commitopen) {
|
||||
if (writestampatomic(stampf, stampwant) != 0) {
|
||||
cerrpath("ww: cannot record ", stampf, "\n");
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user