From c5422f79e211247c07db3d52ad373e8c40d287f5 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Sat, 18 Nov 2006 15:47:42 +0000 Subject: [PATCH] runqueue.py: Change failed tasks handling so all failed tasks are reported, not just the first. Also add signal handling so Ctrl+C only interrupts the main tasks upon the first keypress, the second keypress sends SIGTERM to all children --- bin/bitbake | 6 ++--- lib/bb/runqueue.py | 69 +++++++++++++++++++++++++++++++++++------------------- lib/bb/shell.py | 5 ++-- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/bin/bitbake b/bin/bitbake index 403f7b8..253ee09 100755 --- a/bin/bitbake +++ b/bin/bitbake @@ -643,10 +643,10 @@ class BBCooker: rq.prepare_runqueue(self.configuration.data, self.status, taskdata, runlist) try: failures = rq.execute_runqueue(self, self.configuration.data, self.status, taskdata, runlist) - except runqueue.TaskFailure, (fnid, fn, taskname): - bb.msg.error(bb.msg.domain.Build, "'%s, %s' failed" % (fn, taskname)) + except runqueue.TaskFailure, fnids: + for fnid in fnids: + bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid]) sys.exit(1) - bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.event_data, failures)) sys.exit( self.stats.show() ) diff --git a/lib/bb/runqueue.py b/lib/bb/runqueue.py index 0a948ca..05027c9 100644 --- a/lib/bb/runqueue.py +++ b/lib/bb/runqueue.py @@ -1,4 +1,4 @@ - #!/usr/bin/env python +#!/usr/bin/env python # ex:ts=4:sw=4:sts=4:et # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- """ @@ -25,9 +25,8 @@ import bb, os, sys class TaskFailure(Exception): """Exception raised when a task in a runqueue fails""" - - def __init__(self, fnid, fn, taskname): - self.args = fnid, fn, taskname + def __init__(self, x): + self.args = x class RunQueue: """ @@ -319,21 +318,23 @@ class RunQueue: failures = 0 while 1: - try: - self.execute_runqueue_internal(cooker, cfgData, dataCache, taskData) + failed_fnids = self.execute_runqueue_internal(cooker, cfgData, dataCache, taskData) + if len(failed_fnids) == 0: return failures - except bb.runqueue.TaskFailure, (fnid, taskData.fn_index[fnid], taskname): - if taskData.abort: - raise + if taskData.abort: + raise bb.runqueue.TaskFailure(failed_fnids) + for fnid in failed_fnids: + #print "Failure: %s %s %s" % (fnid, taskData.fn_index[fnid], self.runq_task[fnid]) taskData.fail_fnid(fnid) - self.reset_runqueue() - self.prepare_runqueue(cfgData, dataCache, taskData, runlist) failures = failures + 1 + self.reset_runqueue() + self.prepare_runqueue(cfgData, dataCache, taskData, runlist) def execute_runqueue_internal(self, cooker, cfgData, dataCache, taskData): """ Run the tasks in a queue prepared by prepare_runqueue """ + import signal bb.msg.note(1, bb.msg.domain.RunQueue, "Executing runqueue") @@ -342,11 +343,15 @@ class RunQueue: runq_complete = [] active_builds = 0 build_pids = {} + failed_fnids = [] if len(self.runq_fnid) == 0: # nothing to do return + def sigint_handler(signum, frame): + raise KeyboardInterrupt + def get_next_task(data): """ Return the id of the highest priority task that is buildable @@ -414,6 +419,11 @@ class RunQueue: except OSError, e: bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) if pid == 0: + # Bypass finally below + active_builds = 0 + # Stop Ctrl+C being sent to children + signal.signal(signal.SIGINT, signal.SIG_IGN) + sys.stdin = open('/dev/null', 'r') cooker.configuration.cmd = taskname[3:] try: cooker.tryBuild(fn, False) @@ -432,28 +442,39 @@ class RunQueue: if active_builds > 0: result = os.waitpid(-1, 0) active_builds = active_builds - 1 + task = build_pids[result[0]] if result[1] != 0: - bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (build_pids[result[0]], self.get_user_idstring(build_pids[result[0]], taskData))) - raise bb.runqueue.TaskFailure(self.runq_fnid[build_pids[result[0]]], taskData.fn_index[self.runq_fnid[build_pids[result[0]]]], self.runq_task[build_pids[result[0]]]) - task_complete(self, build_pids[result[0]]) + del build_pids[result[0]] + bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task, taskData))) + failed_fnids.append(self.runq_fnid[task]) + break + task_complete(self, task) del build_pids[result[0]] continue break - except SystemExit: - raise - except: - bb.msg.error(bb.msg.domain.RunQueue, "Exception received") - if active_builds > 0: + finally: + try: + orig_builds = active_builds while active_builds > 0: bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % active_builds) tasknum = 1 for k, v in build_pids.iteritems(): - bb.msg.note(1, bb.msg.domain.RunQueue, "%s: %s (%s)" % (tasknum, self.get_user_idstring(v, taskData), k)) - tasknum = tasknum + 1 + bb.msg.note(1, bb.msg.domain.RunQueue, "%s: %s (%s)" % (tasknum, self.get_user_idstring(v, taskData), k)) + tasknum = tasknum + 1 result = os.waitpid(-1, 0) - del build_pids[result[0]] + task = build_pids[result[0]] + if result[1] != 0: + bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task, taskData))) + failed_fnids.append(self.runq_fnid[task]) + del build_pids[result[0]] active_builds = active_builds - 1 - raise + if orig_builds > 0: + return failed_fnids + except: + bb.msg.note(1, bb.msg.domain.RunQueue, "Sending SIGTERM to remaining %s tasks" % active_builds) + for k, v in build_pids.iteritems(): + os.kill(k, signal.SIGTERM) + raise # Sanity Checks for task in range(len(self.runq_fnid)): @@ -464,7 +485,7 @@ class RunQueue: if runq_complete[task] == 0: bb.msg.error(bb.msg.domain.RunQueue, "Task %s never completed!" % task) - return 0 + return failed_fnids def dump_data(self, taskQueue): """ diff --git a/lib/bb/shell.py b/lib/bb/shell.py index 760c371..711cd43 100644 --- a/lib/bb/shell.py +++ b/lib/bb/shell.py @@ -179,8 +179,9 @@ class BitBakeShellCommands: global last_exception last_exception = Providers.NoProvider - except runqueue.TaskFailure, (fnid, fn, taskname): - print "ERROR: '%s, %s' failed" % (fn, taskname) + except runqueue.TaskFailure, fnids: + for fnid in fnids: + print "ERROR: '%s' failed" % td.fn_index[fnid]) global last_exception last_exception = runqueue.TaskFailure -- 2.7.4