Ensure completion stages run when 'stop build' is hit.

When a developer hits 'stop build' on a paladin builder, the master
paladin will wait forever. This is not the expected behavior. Similarly,
when Pre-CQ runs, if somebody stops the build, the CL will never be
approved by the Pre-CQ, and will be left waiting for a very long time
(the CQ will eventually pick it up when no other CLs are waiting.)

BUG=chromium:214624, chromium:246260
TEST=Run example remote trybot run and verify completion stage runs
     when you hit stop build
TEST=Run unit tests.
TEST=Run pre-cq with real change, hit stop build, and verify completion
     stage runs.
TEST=Run successful paladin run

CQ-DEPEND=CL:62429, CL:62427
Change-Id: Idea5587178ff0ac86a07bf38d238aeafa44b3071
Reviewed-on: https://gerrit.chromium.org/gerrit/59361
Commit-Queue: David James <davidjames@chromium.org>
Reviewed-by: David James <davidjames@chromium.org>
Tested-by: David James <davidjames@chromium.org>
diff --git a/scripts/cbuildbot.py b/scripts/cbuildbot.py
index 5b4a230..0e3d04f 100644
--- a/scripts/cbuildbot.py
+++ b/scripts/cbuildbot.py
@@ -539,17 +539,21 @@
   def RunStages(self):
     """Runs simple builder logic and publishes information to overlays."""
     was_build_successful = False
-    try:
-      super(DistributedBuilder, self).RunStages()
-      was_build_successful = results_lib.Results.BuildSucceededSoFar()
-    except SystemExit as ex:
-      # If a stage calls sys.exit(0), it's exiting with success, so that means
-      # we should mark ourselves as successful.
-      if ex.code == 0:
-        was_build_successful = True
-      raise
-    finally:
-      self.Publish(was_build_successful)
+    with cleanup.EnforcedCleanupSection() as critical_section:
+      try:
+        # Mark everything between EnforcedCleanupSection and here as having to
+        # be rolled back via the contextmanager cleanup handlers.
+        critical_section.ForkWatchdog()
+        super(DistributedBuilder, self).RunStages()
+        was_build_successful = results_lib.Results.BuildSucceededSoFar()
+      except SystemExit as ex:
+        # If a stage calls sys.exit(0), it's exiting with success, so that means
+        # we should mark ourselves as successful.
+        if ex.code == 0:
+          was_build_successful = True
+        raise
+      finally:
+        self.Publish(was_build_successful)
 
 
 def _ConfirmBuildRoot(buildroot):