Skip to content

Commit 8791c2c

Browse files
committed
fix(build): publish compiler records in host filesystem namespace
1 parent 0cc3968 commit 8791c2c

3 files changed

Lines changed: 14 additions & 52 deletions

File tree

‎src/build/schedule/compiler_transaction.cpp‎

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -23,56 +23,20 @@ bool replace_record(const fs::path& path,std::string_view bytes,std::string* dia
2323
output.close();
2424
const bool closed=bool(output);
2525
if(written&&closed) {
26-
auto renamed=os::fs::rename(temporary,path,true);
27-
if(renamed)return true;
26+
// The temporary was created through std::filesystem's host namespace.
27+
// Publish it through the same namespace, in this same directory. A
28+
// The detached controller's OpenKal lookup rejected this exact file
29+
// on Windows even though the host filesystem could rename it.
30+
std::error_code renamed;
31+
fs::rename(temporary,path,renamed);
32+
if(!renamed)return true;
2833
if(diagnostic) {
29-
// The OpenKal condition does not retain the Windows NTSTATUS. These
30-
// observations distinguish a blocked replacement from a source or
31-
// parent failure without exposing private build paths in CI logs.
3234
std::error_code sourceError, targetError;
3335
const auto source=fs::symlink_status(temporary,sourceError);
3436
const auto target=fs::symlink_status(path,targetError);
35-
std::string probeReport;
36-
// A final status is a new name. If the replace form itself was
37-
// refused as invalid while that name is absent, try the atomic
38-
// no-replace form on the exact same source and destination. Its
39-
// refusal is preserved as evidence rather than hidden by a loop.
40-
int noReplaceCode=0;
41-
const bool targetAbsent=target.type()==fs::file_type::not_found
42-
|| targetError==std::errc::no_such_file_or_directory;
43-
if(renamed.error().code==os::errc::invalid && fs::is_regular_file(source)
44-
&& targetAbsent) {
45-
auto noReplace=os::fs::rename(temporary,path,false);
46-
if(noReplace) {
47-
*diagnostic="replace form refused absent target; no-replace published";
48-
return true;
49-
}
50-
noReplaceCode=static_cast<int>(noReplace.error().code);
51-
}
52-
#if defined(_WIN32)
53-
// CI-only root-cause probe. Remove before merge: it intentionally
54-
// compares the standard library's rename of this exact source to
55-
// a distinct diagnostic name, without publishing the status.
56-
if(noReplaceCode==static_cast<int>(os::errc::invalid)) {
57-
const auto sourceLocation=os::fs::locate(temporary);
58-
const auto targetLocation=os::fs::locate(path);
59-
const auto readable=os::fs::read(temporary);
60-
auto probe=temporary;probe+=".diagnostic";
61-
std::error_code nativeError;
62-
fs::rename(temporary,probe,nativeError);
63-
if(!nativeError) {std::error_code ignored;fs::remove(probe,ignored);}
64-
probeReport=std::format(
65-
"; CI probe source-rel {} target-rel {} same-root {} KAL-read {} std-rename-code {} category {}",
66-
sourceLocation?sourceLocation->relative.size():0,
67-
targetLocation?targetLocation->relative.size():0,
68-
sourceLocation&&targetLocation&&sourceLocation->directory==targetLocation->directory,
69-
readable?0:static_cast<int>(readable.error().code),
70-
nativeError.value(),nativeError.category().name());
71-
}
72-
#endif
73-
*diagnostic=std::format("rename temporary (condition {}, native {}; source regular {} ec {}; target exists {} ec {}; no-replace condition {}{})",
74-
static_cast<int>(renamed.error().code),renamed.error().native,
75-
fs::is_regular_file(source),sourceError.value(),fs::exists(target),targetError.value(),noReplaceCode,probeReport);
37+
*diagnostic=std::format("rename temporary (system {} {}; source regular {} ec {}; target exists {} ec {})",
38+
renamed.value(),renamed.category().name(),
39+
fs::is_regular_file(source),sourceError.value(),fs::exists(target),targetError.value());
7640
}
7741
} else if(!written) {
7842
fail("write/flush temporary");

‎src/build/schedule/detach_codegen.cppm‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -317,12 +317,10 @@ bool write_rc(const std::filesystem::path& slot, int rc,std::string* diagnostic=
317317
std::string localDiagnostic;
318318
auto* detail=diagnostic?diagnostic:&localDiagnostic;
319319
const bool written=transactions::replace_record(suffixed(slot,".rc"),std::to_string(rc)+"\n",detail);
320-
#if defined(_WIN32)
321-
// CI-only: early supervisor failures have no caller-owned diagnostic.
322-
// Report their status-publication failure without printing private paths.
320+
// An early supervisor failure has no caller-owned diagnostic. Keep its
321+
// status-publication error beside the compiler log for the waiter.
323322
if(!written&&!diagnostic)
324-
record_supervisor_error(slot,std::format("CI early status publication: {}",localDiagnostic));
325-
#endif
323+
record_supervisor_error(slot,std::format("cannot publish compiler status: {}",localDiagnostic));
326324
return written;
327325
}
328326

‎tests/unit/test_compiler_transaction.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ TEST(CompilerTransaction, FailedRenameReportsTheStageAndPreservesItsTarget) {
235235
fs::create_directory(t.root/"record");
236236
std::string diagnostic;
237237
EXPECT_FALSE(tx::replace_record(t.root/"record","replacement",&diagnostic));
238-
EXPECT_TRUE(diagnostic.starts_with("rename temporary (condition "))<<diagnostic;
238+
EXPECT_TRUE(diagnostic.starts_with("rename temporary (system "))<<diagnostic;
239239
EXPECT_TRUE(fs::is_directory(t.root/"record"));
240240
}
241241
TEST(CompilerTransaction, ReaderHeldTargetKeepsAnAtomicRecord) {

0 commit comments

Comments
 (0)