aboutsummaryrefslogtreecommitdiff
path: root/ninja.cc
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2015-09-14 15:11:45 -0700
committerColin Cross <ccross@android.com>2015-09-14 15:21:31 -0700
commit0850f7d9192fa5dda7030617a9d7d28d4ea91226 (patch)
tree83befb03e924e1f390d4c97557860bcc7c812edb /ninja.cc
parent36b6582e5690f473f8ebbd6e255df92b955c696e (diff)
Write .kati_stamp file atomically
It is possible to get a mismatch between the .kati_stamp file and the build.ninja file by exiting due to error or interrupt after the ninja file is written but before the stamp file is written. If the change that caused the previous stamp file verification to fail are then reverted, for example an environment variable set back to what it was in the stamp file, the next run of kati could see the old stamp file and not rewrite the non-matching ninja file. To avoid stamp and ninja file mismatches, delete the old stamp file just before starting to write any new files. To avoid a partially written stamp file write the stamp file to .kati_stamp.tmp, and then atomically rename it to .kati_stamp. Change-Id: Id5c7d7ab2b7f051a430ebbf919b8535b219ca290
Diffstat (limited to 'ninja.cc')
-rw-r--r--ninja.cc14
1 files changed, 13 insertions, 1 deletions
diff --git a/ninja.cc b/ninja.cc
index ef74e35..15b659d 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -194,6 +194,7 @@ class NinjaGenerator {
void Generate(const vector<DepNode*>& nodes,
bool build_all_targets,
const string& orig_args) {
+ unlink(GetStampFilename().c_str());
GenerateNinja(nodes, build_all_targets, orig_args);
GenerateShell();
GenerateStamp(orig_args);
@@ -206,6 +207,11 @@ class NinjaGenerator {
ninja_suffix ? ninja_suffix : "");
}
+ static string GetStampTempFilename(const char* ninja_dir,
+ const char* ninja_suffix) {
+ return StringPrintf("%s.tmp", GetStampFilename(ninja_dir, ninja_suffix).c_str());
+ }
+
private:
string GenRuleName() {
return StringPrintf("rule%d", rule_id_++);
@@ -559,6 +565,10 @@ class NinjaGenerator {
return GetStampFilename(ninja_dir_.c_str(), ninja_suffix_.c_str());
}
+ string GetStampTempFilename() const {
+ return GetStampTempFilename(ninja_dir_.c_str(), ninja_suffix_.c_str());
+ }
+
void GenerateNinja(const vector<DepNode*>& nodes,
bool build_all_targets,
const string& orig_args) {
@@ -639,7 +649,7 @@ class NinjaGenerator {
}
void GenerateStamp(const string& orig_args) {
- FILE* fp = fopen(GetStampFilename().c_str(), "wb");
+ FILE* fp = fopen(GetStampTempFilename().c_str(), "wb");
CHECK(fp);
size_t r = fwrite(&start_time_, sizeof(start_time_), 1, fp);
@@ -716,6 +726,8 @@ class NinjaGenerator {
DumpString(fp, orig_args);
fclose(fp);
+
+ rename(GetStampTempFilename().c_str(), GetStampFilename().c_str());
}
CommandEvaluator ce_;