@@ -856,7 +856,7 @@ class BuildEngineImpl {
856
856
ruleInfo->keyID , ruleInfo->rule , ruleInfo->result , &error);
857
857
if (!result) {
858
858
delegate.error (error);
859
- completeRemainingTasks ();
859
+ cancelRemainingTasks ();
860
860
return false ;
861
861
}
862
862
}
@@ -891,6 +891,10 @@ class BuildEngineImpl {
891
891
892
892
// If we haven't done any other work at this point but we have pending
893
893
// tasks, we need to wait for a task to complete.
894
+ //
895
+ // NOTE: Cancellation also implements this process, if you modify this
896
+ // code please also validate that \see cancelRemainingTasks() is still
897
+ // correct.
894
898
if (!didWork && numOutstandingUnfinishedTasks != 0 ) {
895
899
TracingInterval i (EngineQueueItemKind::Waiting);
896
900
@@ -901,7 +905,7 @@ class BuildEngineImpl {
901
905
// of the mutex, if one has been added then we may have already missed
902
906
// the condition notification and cannot safely wait.
903
907
if (finishedTaskInfos.empty ()) {
904
- finishedTaskInfosCondition.wait (lock);
908
+ finishedTaskInfosCondition.wait (lock);
905
909
}
906
910
907
911
didWork = true ;
@@ -1054,17 +1058,45 @@ class BuildEngineImpl {
1054
1058
assert (!cycleList.empty ());
1055
1059
1056
1060
delegate.cycleDetected (cycleList);
1057
- completeRemainingTasks ();
1061
+ cancelRemainingTasks ();
1058
1062
}
1059
1063
1060
- // Complete all of the remaining tasks.
1061
- //
1062
- // FIXME: Should we have a task abort callback?
1063
- void completeRemainingTasks () {
1064
+ // Cancel all of the remaining tasks.
1065
+ void cancelRemainingTasks () {
1066
+ // We need to wait for any currently running tasks to be reported as
1067
+ // complete. Not doing this would mean we could get asynchronous calls
1068
+ // attempting to modify the task state concurrently with the cancellation
1069
+ // process, which isn't something we want to need to synchronize on.
1070
+ //
1071
+ // We don't process the requests at all, we simply drain them. In practice,
1072
+ // we expect clients to implement cancellation in conjection with causing
1073
+ // long-running tasks to also cancel and fail, so preserving those results
1074
+ // is not valuable.
1075
+ while (numOutstandingUnfinishedTasks != 0 ) {
1076
+ std::unique_lock<std::mutex> lock (finishedTaskInfosMutex);
1077
+ if (finishedTaskInfos.empty ()) {
1078
+ finishedTaskInfosCondition.wait (lock);
1079
+ } else {
1080
+ assert (finishedTaskInfos.size () <= numOutstandingUnfinishedTasks);
1081
+ numOutstandingUnfinishedTasks -= finishedTaskInfos.size ();
1082
+ finishedTaskInfos.clear ();
1083
+ }
1084
+ }
1085
+
1064
1086
for (auto & it: taskInfos) {
1065
- // Complete the task, even though it did not update the value.
1087
+ // Cancel the task, marking it incomplete.
1088
+ //
1089
+ // This will force it to rerun in a later build, but since it was already
1090
+ // running in this build that was almost certainly going to be
1091
+ // required. Technically, there are rare situations where it wouldn't have
1092
+ // to rerun (e.g., if resultIsValid becomes true after being false in this
1093
+ // run), and if we were willing to restore the tasks state--either by
1094
+ // keeping the old one or by restoring from the database--we could ensure
1095
+ // that doesn't happen.
1066
1096
//
1067
- // FIXME: What should we do here with the value?
1097
+ // NOTE: Actually, we currently don't sync this write to the database, so
1098
+ // in some cases we do actually preserve this information (if the client
1099
+ // ends up cancelling, then reloading froom the database).
1068
1100
TaskInfo* taskInfo = &it.second ;
1069
1101
RuleInfo* ruleInfo = taskInfo->forRuleInfo ;
1070
1102
assert (taskInfo == ruleInfo->getPendingTaskInfo ());
@@ -1176,7 +1208,7 @@ class BuildEngineImpl {
1176
1208
db->lookupRuleResult (ruleInfo.keyID , ruleInfo.rule , &ruleInfo.result , &error);
1177
1209
if (!error.empty ()) {
1178
1210
delegate.error (error);
1179
- completeRemainingTasks ();
1211
+ cancelRemainingTasks ();
1180
1212
}
1181
1213
}
1182
1214
@@ -1350,7 +1382,7 @@ class BuildEngineImpl {
1350
1382
// Validate the InputID.
1351
1383
if (inputID > BuildEngine::kMaximumInputID ) {
1352
1384
delegate.error (" error: attempt to use reserved input ID" );
1353
- completeRemainingTasks ();
1385
+ cancelRemainingTasks ();
1354
1386
return ;
1355
1387
}
1356
1388
@@ -1368,7 +1400,7 @@ class BuildEngineImpl {
1368
1400
1369
1401
if (!taskInfo->forRuleInfo ->isInProgressComputing ()) {
1370
1402
delegate.error (" error: invalid state for adding discovered dependency" );
1371
- completeRemainingTasks ();
1403
+ cancelRemainingTasks ();
1372
1404
return ;
1373
1405
}
1374
1406
@@ -1385,7 +1417,7 @@ class BuildEngineImpl {
1385
1417
1386
1418
if (!taskInfo->forRuleInfo ->isInProgressComputing ()) {
1387
1419
delegate.error (" error: invalid state for marking task complete" );
1388
- completeRemainingTasks ();
1420
+ cancelRemainingTasks ();
1389
1421
return ;
1390
1422
}
1391
1423
0 commit comments