summaryrefslogtreecommitdiffstats
path: root/src/deps_log.cc
diff options
context:
space:
mode:
authorJan Niklas Hasse <jhasse@bixense.com>2020-05-18 10:46:18 (GMT)
committerJan Niklas Hasse <jhasse@bixense.com>2020-05-23 16:44:25 (GMT)
commitcc79afbc0510b7320d35fb481f0f200dec92cb43 (patch)
tree51485cf06f219f729167299f428242ed8c2cb04a /src/deps_log.cc
parentcf021f32e62370b7f9c8249a6c600cbe48e849c7 (diff)
downloadNinja-cc79afbc0510b7320d35fb481f0f200dec92cb43.zip
Ninja-cc79afbc0510b7320d35fb481f0f200dec92cb43.tar.gz
Ninja-cc79afbc0510b7320d35fb481f0f200dec92cb43.tar.bz2
Delay actually opening log files until the first write, fix #1724
Calling DepsLog/BuildLog::OpenForWrite will now only save the file path. The actual opening of the file (moved to OpenForWriteIfNeeded) happens right before the first write attempt. This is needed so that the files aren't held open when the generator runs (i.e. RebuildManifest) as it may call tools like recompact which won't be able to open the file on Windows. The disadvantage is that now the error reporting happens at a later time and will be reported as a failed write, not a failed open.
Diffstat (limited to 'src/deps_log.cc')
-rw-r--r--src/deps_log.cc72
1 files changed, 44 insertions, 28 deletions
diff --git a/src/deps_log.cc b/src/deps_log.cc
index cf55194..db8f071 100644
--- a/src/deps_log.cc
+++ b/src/deps_log.cc
@@ -49,34 +49,9 @@ bool DepsLog::OpenForWrite(const string& path, string* err) {
return false;
}
- file_ = fopen(path.c_str(), "ab");
- if (!file_) {
- *err = strerror(errno);
- return false;
- }
- // Set the buffer size to this and flush the file buffer after every record
- // to make sure records aren't written partially.
- setvbuf(file_, NULL, _IOFBF, kMaxRecordSize + 1);
- SetCloseOnExec(fileno(file_));
-
- // Opening a file in append mode doesn't set the file pointer to the file's
- // end on Windows. Do that explicitly.
- fseek(file_, 0, SEEK_END);
-
- if (ftell(file_) == 0) {
- if (fwrite(kFileSignature, sizeof(kFileSignature) - 1, 1, file_) < 1) {
- *err = strerror(errno);
- return false;
- }
- if (fwrite(&kCurrentVersion, 4, 1, file_) < 1) {
- *err = strerror(errno);
- return false;
- }
- }
- if (fflush(file_) != 0) {
- *err = strerror(errno);
- return false;
- }
+ assert(!file_);
+ file_path_ = path; // we don't actually open the file right now, but will do
+ // so on the first write attempt
return true;
}
@@ -132,6 +107,10 @@ bool DepsLog::RecordDeps(Node* node, TimeStamp mtime,
errno = ERANGE;
return false;
}
+
+ if (!OpenForWriteIfNeeded()) {
+ return false;
+ }
size |= 0x80000000; // Deps record: set high bit.
if (fwrite(&size, 4, 1, file_) < 1)
return false;
@@ -162,6 +141,7 @@ bool DepsLog::RecordDeps(Node* node, TimeStamp mtime,
}
void DepsLog::Close() {
+ OpenForWriteIfNeeded(); // create the file even if nothing has been recorded
if (file_)
fclose(file_);
file_ = NULL;
@@ -396,6 +376,10 @@ bool DepsLog::RecordId(Node* node) {
errno = ERANGE;
return false;
}
+
+ if (!OpenForWriteIfNeeded()) {
+ return false;
+ }
if (fwrite(&size, 4, 1, file_) < 1)
return false;
if (fwrite(node->path().data(), path_size, 1, file_) < 1) {
@@ -416,3 +400,35 @@ bool DepsLog::RecordId(Node* node) {
return true;
}
+
+bool DepsLog::OpenForWriteIfNeeded() {
+ if (file_path_.empty()) {
+ return true;
+ }
+ file_ = fopen(file_path_.c_str(), "ab");
+ if (!file_) {
+ return false;
+ }
+ // Set the buffer size to this and flush the file buffer after every record
+ // to make sure records aren't written partially.
+ setvbuf(file_, NULL, _IOFBF, kMaxRecordSize + 1);
+ SetCloseOnExec(fileno(file_));
+
+ // Opening a file in append mode doesn't set the file pointer to the file's
+ // end on Windows. Do that explicitly.
+ fseek(file_, 0, SEEK_END);
+
+ if (ftell(file_) == 0) {
+ if (fwrite(kFileSignature, sizeof(kFileSignature) - 1, 1, file_) < 1) {
+ return false;
+ }
+ if (fwrite(&kCurrentVersion, 4, 1, file_) < 1) {
+ return false;
+ }
+ }
+ if (fflush(file_) != 0) {
+ return false;
+ }
+ file_path_.clear();
+ return true;
+}