aboutsummaryrefslogtreecommitdiff
path: root/build2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-03-08 11:08:58 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-03-08 11:08:58 +0200
commitbe1aefb4c5a9b4c41aa780edce52c6ac91ccdfe5 (patch)
tree959c1ac962e7a73f18495fefea649cda097a11ec /build2
parente2210969b337f3888ba9fb7617a009ca9bb2979a (diff)
Fix depdb/target update race
Diffstat (limited to 'build2')
-rw-r--r--build2/cxx/compile.cxx5
-rw-r--r--build2/depdb19
2 files changed, 18 insertions, 6 deletions
diff --git a/build2/cxx/compile.cxx b/build2/cxx/compile.cxx
index 6382188..015d538 100644
--- a/build2/cxx/compile.cxx
+++ b/build2/cxx/compile.cxx
@@ -221,9 +221,10 @@ namespace build2
}
// If any of the above checks resulted in a mismatch (different
- // compiler, options, or source file), then force the target update.
+ // compiler, options, or source file), or if the database is newer
+ // than the target (interrupted update) then force the target update.
//
- if (dd.writing ())
+ if (dd.writing () || dd.mtime () > t.mtime ())
t.mtime (timestamp_nonexistent);
inject_prerequisites (a, t, st, mr.prerequisite->scope, dd);
diff --git a/build2/depdb b/build2/depdb
index effdc92..be45d91 100644
--- a/build2/depdb
+++ b/build2/depdb
@@ -13,7 +13,8 @@
namespace build2
{
- // Auxiliary dependency database (those .d files).
+ // Auxiliary dependency database (those .d files). Uses iostream failure and
+ // system_error exceptions to signal errors.
//
// This is a strange beast: a line-oriented, streaming database that can, at
// some point, be switched from reading to (over)writing. The idea is to
@@ -45,7 +46,16 @@ namespace build2
// /tmp/foo/bar.hxx
// ^@
//
- // Uses iostream failure and system_error exceptions to signal errors.
+ // A race is possible between updating the database and the target. For
+ // example, we may detect a line mismatch that renders the target out-of-
+ // date (say, compile options in the above example). We update the database
+ // but before getting a chance to update the target, we get interrupted. On
+ // a subsequent re-run, because the database has been updated, we will miss
+ // the "target requires update" condition.
+ //
+ // If we assume that an update of the database also means an update of the
+ // target, then this "interrupted update" situation can be easily detected
+ // by comparing the database and target modification timestamps.
//
class depdb
{
@@ -69,8 +79,9 @@ namespace build2
void
touch () {touch_ = true;}
- // Close the database. Note that if this function is not called, then
- // the database may be left in the old/currupt state.
+ // Close the database. If this function is not called, then the database
+ // may be left in the old/currupt state. Note that in the read mode this
+ // function will "chop off" lines that haven't been read.
//
void
close ();