about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-08-30T13·45+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-08-30T13·45+0200
commit97b1af1cbe03a48793426bee883ad9c4c9fd7db8 (patch)
tree941a6c121ac775474129da82cefff096bff7d04b /src
parentdd85fc1c5a302eb8566fb44c6300c7add20e569d (diff)
Fix --fallback
This fixes an assertion failure in "assert(goal);" in
Worker::waitForInput() after a substitution goal is cancelled by the
termination of another goal. The problem was the line

  //worker.childTerminated(shared_from_this()); // FIXME

in the SubstitutionGoal destructor. This was disabled because
shared_from_this() obviously doesn't work from a destructor. So we now
use a real pointer for object identity.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/build.cc17
1 files changed, 10 insertions, 7 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 0c687dfc1386..e0eb702a4f82 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -193,6 +193,7 @@ bool CompareGoalPtrs::operator() (const GoalPtr & a, const GoalPtr & b) {
 struct Child
 {
     WeakGoalPtr goal;
+    Goal * goal2; // ugly hackery
     set<int> fds;
     bool respectTimeouts;
     bool inBuildSlot;
@@ -284,7 +285,7 @@ public:
        false if there is no sense in waking up goals that are sleeping
        because they can't run yet (e.g., there is no free build slot,
        or the hook would still say `postpone'). */
-    void childTerminated(GoalPtr goal, bool wakeSleepers = true);
+    void childTerminated(Goal * goal, bool wakeSleepers = true);
 
     /* Put `goal' to sleep until a build slot becomes available (which
        might be right away). */
@@ -935,7 +936,7 @@ DerivationGoal::~DerivationGoal()
 void DerivationGoal::killChild()
 {
     if (pid != -1) {
-        worker.childTerminated(shared_from_this());
+        worker.childTerminated(this);
 
         if (buildUser.enabled()) {
             /* If we're using a build user, then there is a tricky
@@ -1409,7 +1410,7 @@ void DerivationGoal::buildDone()
     debug(format("builder process for ‘%1%’ finished") % drvPath);
 
     /* So the child is gone now. */
-    worker.childTerminated(shared_from_this());
+    worker.childTerminated(this);
 
     /* Close the read side of the logger pipe. */
     if (hook) {
@@ -3141,8 +3142,9 @@ SubstitutionGoal::~SubstitutionGoal()
 {
     try {
         if (thr.joinable()) {
+            // FIXME: signal worker thread to quit.
             thr.join();
-            //worker.childTerminated(shared_from_this()); // FIXME
+            worker.childTerminated(this);
         }
     } catch (...) {
         ignoreException();
@@ -3297,7 +3299,7 @@ void SubstitutionGoal::finished()
     trace("substitute finished");
 
     thr.join();
-    worker.childTerminated(shared_from_this());
+    worker.childTerminated(this);
 
     try {
         promise.get_future().get();
@@ -3450,6 +3452,7 @@ void Worker::childStarted(GoalPtr goal, const set<int> & fds,
 {
     Child child;
     child.goal = goal;
+    child.goal2 = goal.get();
     child.fds = fds;
     child.timeStarted = child.lastOutput = time(0);
     child.inBuildSlot = inBuildSlot;
@@ -3459,10 +3462,10 @@ void Worker::childStarted(GoalPtr goal, const set<int> & fds,
 }
 
 
-void Worker::childTerminated(GoalPtr goal, bool wakeSleepers)
+void Worker::childTerminated(Goal * goal, bool wakeSleepers)
 {
     auto i = std::find_if(children.begin(), children.end(),
-        [&](const Child & child) { return child.goal.lock() == goal; });
+        [&](const Child & child) { return child.goal2 == goal; });
     assert(i != children.end());
 
     if (i->inBuildSlot) {