Skip to content

Commit a676ab6

Browse files
committed
[Frontend]: Write out .swiftdeps files atomically
Modify ReferenceDependenciesEmitter::emit to write to a temporary file and then atomically rename it in place using the atomicallyWritingToFile helper function. This resolves SR-8707, where .swiftdeps files could be truncated if the compiler job was killed in the middle of a write.
1 parent da8eb3c commit a676ab6

File tree

1 file changed

+12
-27
lines changed

1 file changed

+12
-27
lines changed

Diff for: lib/FrontendTool/ReferenceDependencies.cpp

+12-27
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/NameLookup.h"
2323
#include "swift/AST/ReferencedNameTracker.h"
2424
#include "swift/AST/Types.h"
25+
#include "swift/Basic/FileSystem.h"
2526
#include "swift/Basic/LLVM.h"
2627
#include "swift/Basic/ReferenceDependencyKeys.h"
2728
#include "swift/Frontend/FrontendOptions.h"
@@ -65,11 +66,6 @@ class ReferenceDependenciesEmitter {
6566
llvm::raw_ostream &out);
6667

6768
private:
68-
/// Opens file for reference dependencies. Emits diagnostic if needed.
69-
///
70-
/// \return nullptr on error
71-
static std::unique_ptr<llvm::raw_fd_ostream> openFile(DiagnosticEngine &diags,
72-
StringRef OutputPath);
7369
/// Emits all the dependency information.
7470
void emit() const;
7571

@@ -189,35 +185,24 @@ static std::string escape(DeclBaseName name) {
189185
return llvm::yaml::escape(name.userFacingName());
190186
}
191187

192-
std::unique_ptr<llvm::raw_fd_ostream>
193-
ReferenceDependenciesEmitter::openFile(DiagnosticEngine &diags,
194-
StringRef outputPath) {
188+
bool ReferenceDependenciesEmitter::emit(DiagnosticEngine &diags,
189+
SourceFile *const SF,
190+
const DependencyTracker &depTracker,
191+
StringRef outputPath) {
195192
// Before writing to the dependencies file path, preserve any previous file
196193
// that may have been there. No error handling -- this is just a nicety, it
197194
// doesn't matter if it fails.
198195
llvm::sys::fs::rename(outputPath, outputPath + "~");
199-
200-
std::error_code EC;
201-
auto out = llvm::make_unique<llvm::raw_fd_ostream>(outputPath, EC,
202-
llvm::sys::fs::F_None);
203-
204-
if (out->has_error() || EC) {
196+
std::error_code EC =
197+
swift::atomicallyWritingToFile(outputPath,
198+
[&](llvm::raw_pwrite_stream &out) {
199+
ReferenceDependenciesEmitter::emit(SF, depTracker, out);
200+
});
201+
if (EC) {
205202
diags.diagnose(SourceLoc(), diag::error_opening_output, outputPath,
206203
EC.message());
207-
out->clear_error();
208-
return nullptr;
209-
}
210-
return out;
211-
}
212-
213-
bool ReferenceDependenciesEmitter::emit(DiagnosticEngine &diags,
214-
SourceFile *const SF,
215-
const DependencyTracker &depTracker,
216-
StringRef outputPath) {
217-
const std::unique_ptr<llvm::raw_ostream> out = openFile(diags, outputPath);
218-
if (!out.get())
219204
return true;
220-
ReferenceDependenciesEmitter::emit(SF, depTracker, *out);
205+
}
221206
return false;
222207
}
223208

0 commit comments

Comments
 (0)