diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-03-08 11:08:58 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-03-08 11:08:58 +0200 |
commit | be1aefb4c5a9b4c41aa780edce52c6ac91ccdfe5 (patch) | |
tree | 959c1ac962e7a73f18495fefea649cda097a11ec | |
parent | e2210969b337f3888ba9fb7617a009ca9bb2979a (diff) |
Fix depdb/target update race
-rw-r--r-- | build2/cxx/compile.cxx | 5 | ||||
-rw-r--r-- | build2/depdb | 19 |
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 (); |