diff options
Diffstat (limited to 'bitbake/lib/bb/runqueue.py')
| -rw-r--r-- | bitbake/lib/bb/runqueue.py | 72 |
1 files changed, 46 insertions, 26 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py index 3dde9a9ffb..07821e23de 100644 --- a/bitbake/lib/bb/runqueue.py +++ b/bitbake/lib/bb/runqueue.py | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
| 2 | # ex:ts=4:sw=4:sts=4:et | 2 | # ex:ts=4:sw=4:sts=4:et |
| 3 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- | 3 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- |
| 4 | """ | 4 | """ |
| @@ -25,9 +25,8 @@ import bb, os, sys | |||
| 25 | 25 | ||
| 26 | class TaskFailure(Exception): | 26 | class TaskFailure(Exception): |
| 27 | """Exception raised when a task in a runqueue fails""" | 27 | """Exception raised when a task in a runqueue fails""" |
| 28 | 28 | def __init__(self, x): | |
| 29 | def __init__(self, fnid, fn, taskname): | 29 | self.args = x |
| 30 | self.args = fnid, fn, taskname | ||
| 31 | 30 | ||
| 32 | class RunQueue: | 31 | class RunQueue: |
| 33 | """ | 32 | """ |
| @@ -319,21 +318,23 @@ class RunQueue: | |||
| 319 | 318 | ||
| 320 | failures = 0 | 319 | failures = 0 |
| 321 | while 1: | 320 | while 1: |
| 322 | try: | 321 | failed_fnids = self.execute_runqueue_internal(cooker, cfgData, dataCache, taskData) |
| 323 | self.execute_runqueue_internal(cooker, cfgData, dataCache, taskData) | 322 | if len(failed_fnids) == 0: |
| 324 | return failures | 323 | return failures |
| 325 | except bb.runqueue.TaskFailure, (fnid, taskData.fn_index[fnid], taskname): | 324 | if taskData.abort: |
| 326 | if taskData.abort: | 325 | raise bb.runqueue.TaskFailure(failed_fnids) |
| 327 | raise | 326 | for fnid in failed_fnids: |
| 327 | #print "Failure: %s %s %s" % (fnid, taskData.fn_index[fnid], self.runq_task[fnid]) | ||
| 328 | taskData.fail_fnid(fnid) | 328 | taskData.fail_fnid(fnid) |
| 329 | self.reset_runqueue() | ||
| 330 | self.prepare_runqueue(cfgData, dataCache, taskData, runlist) | ||
| 331 | failures = failures + 1 | 329 | failures = failures + 1 |
| 330 | self.reset_runqueue() | ||
| 331 | self.prepare_runqueue(cfgData, dataCache, taskData, runlist) | ||
| 332 | 332 | ||
| 333 | def execute_runqueue_internal(self, cooker, cfgData, dataCache, taskData): | 333 | def execute_runqueue_internal(self, cooker, cfgData, dataCache, taskData): |
| 334 | """ | 334 | """ |
| 335 | Run the tasks in a queue prepared by prepare_runqueue | 335 | Run the tasks in a queue prepared by prepare_runqueue |
| 336 | """ | 336 | """ |
| 337 | import signal | ||
| 337 | 338 | ||
| 338 | bb.msg.note(1, bb.msg.domain.RunQueue, "Executing runqueue") | 339 | bb.msg.note(1, bb.msg.domain.RunQueue, "Executing runqueue") |
| 339 | 340 | ||
| @@ -342,11 +343,15 @@ class RunQueue: | |||
| 342 | runq_complete = [] | 343 | runq_complete = [] |
| 343 | active_builds = 0 | 344 | active_builds = 0 |
| 344 | build_pids = {} | 345 | build_pids = {} |
| 346 | failed_fnids = [] | ||
| 345 | 347 | ||
| 346 | if len(self.runq_fnid) == 0: | 348 | if len(self.runq_fnid) == 0: |
| 347 | # nothing to do | 349 | # nothing to do |
| 348 | return | 350 | return |
| 349 | 351 | ||
| 352 | def sigint_handler(signum, frame): | ||
| 353 | raise KeyboardInterrupt | ||
| 354 | |||
| 350 | def get_next_task(data): | 355 | def get_next_task(data): |
| 351 | """ | 356 | """ |
| 352 | Return the id of the highest priority task that is buildable | 357 | Return the id of the highest priority task that is buildable |
| @@ -414,6 +419,11 @@ class RunQueue: | |||
| 414 | except OSError, e: | 419 | except OSError, e: |
| 415 | bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) | 420 | bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) |
| 416 | if pid == 0: | 421 | if pid == 0: |
| 422 | # Bypass finally below | ||
| 423 | active_builds = 0 | ||
| 424 | # Stop Ctrl+C being sent to children | ||
| 425 | signal.signal(signal.SIGINT, signal.SIG_IGN) | ||
| 426 | sys.stdin = open('/dev/null', 'r') | ||
| 417 | cooker.configuration.cmd = taskname[3:] | 427 | cooker.configuration.cmd = taskname[3:] |
| 418 | try: | 428 | try: |
| 419 | cooker.tryBuild(fn, False) | 429 | cooker.tryBuild(fn, False) |
| @@ -434,26 +444,36 @@ class RunQueue: | |||
| 434 | active_builds = active_builds - 1 | 444 | active_builds = active_builds - 1 |
| 435 | task = build_pids[result[0]] | 445 | task = build_pids[result[0]] |
| 436 | if result[1] != 0: | 446 | if result[1] != 0: |
| 447 | del build_pids[result[0]] | ||
| 437 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task, taskData))) | 448 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task, taskData))) |
| 438 | raise bb.runqueue.TaskFailure(self.runq_fnid[task], taskData.fn_index[self.runq_fnid[task]], self.runq_task[task]) | 449 | failed_fnids.append(self.runq_fnid[task]) |
| 450 | break | ||
| 439 | task_complete(self, task) | 451 | task_complete(self, task) |
| 440 | del build_pids[result[0]] | 452 | del build_pids[result[0]] |
| 441 | continue | 453 | continue |
| 442 | break | 454 | break |
| 443 | except SystemExit: | 455 | finally: |
| 444 | raise | 456 | try: |
| 445 | except: | 457 | while active_builds > 0: |
| 446 | bb.msg.error(bb.msg.domain.RunQueue, "Exception received") | 458 | bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % active_builds) |
| 447 | while active_builds > 0: | 459 | tasknum = 1 |
| 448 | bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % active_builds) | 460 | for k, v in build_pids.iteritems(): |
| 449 | tasknum = 1 | 461 | bb.msg.note(1, bb.msg.domain.RunQueue, "%s: %s (%s)" % (tasknum, self.get_user_idstring(v, taskData), k)) |
| 462 | tasknum = tasknum + 1 | ||
| 463 | result = os.waitpid(-1, 0) | ||
| 464 | task = build_pids[result[0]] | ||
| 465 | if result[1] != 0: | ||
| 466 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task, taskData))) | ||
| 467 | failed_fnids.append(self.runq_fnid[task]) | ||
| 468 | del build_pids[result[0]] | ||
| 469 | active_builds = active_builds - 1 | ||
| 470 | if len(failed_fnids) > 0: | ||
| 471 | return failed_fnids | ||
| 472 | except: | ||
| 473 | bb.msg.note(1, bb.msg.domain.RunQueue, "Sending SIGTERM to remaining %s tasks" % active_builds) | ||
| 450 | for k, v in build_pids.iteritems(): | 474 | for k, v in build_pids.iteritems(): |
| 451 | bb.msg.note(1, bb.msg.domain.RunQueue, "%s: %s (%s)" % (tasknum, self.get_user_idstring(v, taskData), k)) | 475 | os.kill(k, signal.SIGTERM) |
| 452 | tasknum = tasknum + 1 | 476 | raise |
| 453 | result = os.waitpid(-1, 0) | ||
| 454 | del build_pids[result[0]] | ||
| 455 | active_builds = active_builds - 1 | ||
| 456 | raise | ||
| 457 | 477 | ||
| 458 | # Sanity Checks | 478 | # Sanity Checks |
| 459 | for task in range(len(self.runq_fnid)): | 479 | for task in range(len(self.runq_fnid)): |
| @@ -464,7 +484,7 @@ class RunQueue: | |||
| 464 | if runq_complete[task] == 0: | 484 | if runq_complete[task] == 0: |
| 465 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s never completed!" % task) | 485 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s never completed!" % task) |
| 466 | 486 | ||
| 467 | return 0 | 487 | return failed_fnids |
| 468 | 488 | ||
| 469 | def dump_data(self, taskQueue): | 489 | def dump_data(self, taskQueue): |
| 470 | """ | 490 | """ |
