summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2015-02-18 15:54:56 +0000
committerSam Thursfield <sam.thursfield@codethink.co.uk>2015-02-18 16:32:50 +0000
commiteba2e42855e9413f035e5093d64543184dce6fae (patch)
tree49dd65e174e7d52d8eec4a934c90c833a22797c4
parent46a8e0de14ce2cca4c93ec53648d7e01333bbf65 (diff)
downloadmorph-eba2e42855e9413f035e5093d64543184dce6fae.tar.gz
distbuild: Log in build-step-xx.log files when initiator cancels build
This makes it easier to spot if an incomplete build was due to the user cancelling, or if it represents a dropped connection or internal error.
-rw-r--r--distbuild/initiator.py32
-rw-r--r--distbuild/mainloop.py5
-rw-r--r--morphlib/buildcommand.py10
3 files changed, 31 insertions, 16 deletions
diff --git a/distbuild/initiator.py b/distbuild/initiator.py
index 548ba496..8f9e0c38 100644
--- a/distbuild/initiator.py
+++ b/distbuild/initiator.py
@@ -151,16 +151,17 @@ class Initiator(distbuild.StateMachine):
def _get_output(self, msg):
return self._step_outputs[msg['step_name']]
+ def _write_status_to_build_log(self, f, status):
+ f.write(time.strftime('%Y-%m-%d %H:%M:%S ') + status + '\n')
+ f.flush()
+
def _handle_step_already_started_message(self, msg):
status = '%s is already building on %s' % (
msg['step_name'], msg['worker_name'])
self._app.status(msg=status)
self._open_output(msg)
-
- f = self._get_output(msg)
- f.write(time.strftime('%Y-%m-%d %H:%M:%S ') + status + '\n')
- f.flush()
+ self._write_status_to_build_log(self._get_output(msg), status)
def _handle_step_started_message(self, msg):
status = 'Started building %s on %s' % (
@@ -168,10 +169,7 @@ class Initiator(distbuild.StateMachine):
self._app.status(msg=status)
self._open_output(msg)
-
- f = self._get_output(msg)
- f.write(time.strftime('%Y-%m-%d %H:%M:%S ') + status + '\n')
- f.flush()
+ self._write_status_to_build_log(self._get_output(msg), status)
def _handle_step_output_message(self, msg):
step_name = msg['step_name']
@@ -190,9 +188,7 @@ class Initiator(distbuild.StateMachine):
status = 'Finished building %s' % step_name
self._app.status(msg=status)
- f = self._get_output(msg)
- f.write(time.strftime('%Y-%m-%d %H:%M:%S ') + status + '\n')
-
+ self._write_status_to_build_log(self._get_output(msg), status)
self._close_output(msg)
else:
logging.warning(
@@ -204,9 +200,7 @@ class Initiator(distbuild.StateMachine):
status = 'Build of %s failed.' % step_name
self._app.status(msg=status)
- f = self._get_output(msg)
- f.write(time.strftime('%Y-%m-%d %H:%M:%S ') + status + '\n')
-
+ self._write_status_to_build_log(self._get_output(msg), status)
self._close_output(msg)
else:
logging.warning(
@@ -237,3 +231,13 @@ class Initiator(distbuild.StateMachine):
self.mainloop.queue_event(self._cm, distbuild.StopConnecting())
self._jm.close()
+ def handle_cancel(self):
+ # Note in each build-step.log file that the initiator cancelled: this
+ # makes it easier to tell whether a build was aborted due to a bug or
+ # dropped connection, or if the user cancelled with CTRL+C / SIGINT.
+
+ for f in self._step_outputs.itervalues():
+ self._write_status_to_build_log(f, 'Initiator cancelled')
+ f.close()
+
+ self._step_outputs = {}
diff --git a/distbuild/mainloop.py b/distbuild/mainloop.py
index 97e439f3..f15a3ac1 100644
--- a/distbuild/mainloop.py
+++ b/distbuild/mainloop.py
@@ -57,8 +57,11 @@ class MainLoop(object):
logging.debug('MainLoop.remove_state_machine: %s' % machine)
self._machines.remove(machine)
+ def state_machines_of_type(self, machine_type):
+ return [m for m in self._machines if isinstance(m, machine_type)]
+
def n_state_machines_of_type(self, machine_type):
- return len([m for m in self._machines if isinstance(m, machine_type)])
+ return len(self.state_machines_of_type(machine_type))
def add_event_source(self, event_source):
logging.debug('MainLoop.add_event_source: %s' % event_source)
diff --git a/morphlib/buildcommand.py b/morphlib/buildcommand.py
index a22e689b..c3accf73 100644
--- a/morphlib/buildcommand.py
+++ b/morphlib/buildcommand.py
@@ -574,4 +574,12 @@ class InitiatorBuildCommand(BuildCommand):
self.MAX_RETRIES)
loop.add_state_machine(cm)
- loop.run()
+ try:
+ loop.run()
+ except KeyboardInterrupt:
+ # This will run if the user presses Ctrl+C or sends SIGINT during
+ # the build. It won't trigger on SIGTERM, SIGKILL or unhandled
+ # Python exceptions.
+ logging.info('Received KeyboardInterrupt, aborting.')
+ for initiator in loop.state_machines_of_type(distbuild.Initiator):
+ initiator.handle_cancel()