diff options
author | Richard Purdie <richard@openedhand.com> | 2007-04-01 15:04:49 +0000 |
---|---|---|
committer | Richard Purdie <richard@openedhand.com> | 2007-04-01 15:04:49 +0000 |
commit | 7371e6323c3fb6b0545712e3cf84606644073e77 (patch) | |
tree | e08f25669ec0f0e9d11334909f3b68c0ab6aca19 /bitbake/lib/bb/runqueue.py | |
parent | 8b36dc217443aeeec8493d39561d2bb010336774 (diff) | |
download | poky-7371e6323c3fb6b0545712e3cf84606644073e77.tar.gz |
bitbake: Update to 1.8.1 (inc. various bug fixes, epoch support)
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@1419 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'bitbake/lib/bb/runqueue.py')
-rw-r--r-- | bitbake/lib/bb/runqueue.py | 355 |
1 files changed, 201 insertions, 154 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py index ec94b0f8ba..059f800b65 100644 --- a/bitbake/lib/bb/runqueue.py +++ b/bitbake/lib/bb/runqueue.py | |||
@@ -25,20 +25,47 @@ Handles preparation and execution of a queue of tasks | |||
25 | from bb import msg, data, fetch, event, mkdirhier, utils | 25 | from bb import msg, data, fetch, event, mkdirhier, utils |
26 | from sets import Set | 26 | from sets import Set |
27 | import bb, os, sys | 27 | import bb, os, sys |
28 | import signal | ||
28 | 29 | ||
29 | class TaskFailure(Exception): | 30 | class TaskFailure(Exception): |
30 | """Exception raised when a task in a runqueue fails""" | 31 | """Exception raised when a task in a runqueue fails""" |
31 | def __init__(self, x): | 32 | def __init__(self, x): |
32 | self.args = x | 33 | self.args = x |
33 | 34 | ||
35 | |||
36 | class RunQueueStats: | ||
37 | """ | ||
38 | Holds statistics on the tasks handled by the associated runQueue | ||
39 | """ | ||
40 | def __init__(self): | ||
41 | self.completed = 0 | ||
42 | self.skipped = 0 | ||
43 | self.failed = 0 | ||
44 | |||
45 | def taskFailed(self): | ||
46 | self.failed = self.failed + 1 | ||
47 | |||
48 | def taskCompleted(self): | ||
49 | self.completed = self.completed + 1 | ||
50 | |||
51 | def taskSkipped(self): | ||
52 | self.skipped = self.skipped + 1 | ||
53 | |||
34 | class RunQueue: | 54 | class RunQueue: |
35 | """ | 55 | """ |
36 | BitBake Run Queue implementation | 56 | BitBake Run Queue implementation |
37 | """ | 57 | """ |
38 | def __init__(self): | 58 | def __init__(self, cooker, cfgData, dataCache, taskData, targets): |
39 | self.reset_runqueue() | 59 | self.reset_runqueue() |
60 | self.cooker = cooker | ||
61 | self.dataCache = dataCache | ||
62 | self.taskData = taskData | ||
63 | self.targets = targets | ||
64 | |||
65 | self.number_tasks = int(bb.data.getVar("BB_NUMBER_THREADS", cfgData) or 1) | ||
40 | 66 | ||
41 | def reset_runqueue(self): | 67 | def reset_runqueue(self): |
68 | |||
42 | self.runq_fnid = [] | 69 | self.runq_fnid = [] |
43 | self.runq_task = [] | 70 | self.runq_task = [] |
44 | self.runq_depends = [] | 71 | self.runq_depends = [] |
@@ -46,16 +73,15 @@ class RunQueue: | |||
46 | self.runq_weight = [] | 73 | self.runq_weight = [] |
47 | self.prio_map = [] | 74 | self.prio_map = [] |
48 | 75 | ||
49 | def get_user_idstring(self, task, taskData): | 76 | def get_user_idstring(self, task): |
50 | fn = taskData.fn_index[self.runq_fnid[task]] | 77 | fn = self.taskData.fn_index[self.runq_fnid[task]] |
51 | taskname = self.runq_task[task] | 78 | taskname = self.runq_task[task] |
52 | return "%s, %s" % (fn, taskname) | 79 | return "%s, %s" % (fn, taskname) |
53 | 80 | ||
54 | def prepare_runqueue(self, cooker, cfgData, dataCache, taskData, targets): | 81 | def prepare_runqueue(self): |
55 | """ | 82 | """ |
56 | Turn a set of taskData into a RunQueue and compute data needed | 83 | Turn a set of taskData into a RunQueue and compute data needed |
57 | to optimise the execution order. | 84 | to optimise the execution order. |
58 | targets is list of paired values - a provider name and the task to run | ||
59 | """ | 85 | """ |
60 | 86 | ||
61 | depends = [] | 87 | depends = [] |
@@ -63,12 +89,14 @@ class RunQueue: | |||
63 | runq_build = [] | 89 | runq_build = [] |
64 | runq_done = [] | 90 | runq_done = [] |
65 | 91 | ||
92 | taskData = self.taskData | ||
93 | |||
66 | bb.msg.note(1, bb.msg.domain.RunQueue, "Preparing Runqueue") | 94 | bb.msg.note(1, bb.msg.domain.RunQueue, "Preparing Runqueue") |
67 | 95 | ||
68 | for task in range(len(taskData.tasks_name)): | 96 | for task in range(len(taskData.tasks_name)): |
69 | fnid = taskData.tasks_fnid[task] | 97 | fnid = taskData.tasks_fnid[task] |
70 | fn = taskData.fn_index[fnid] | 98 | fn = taskData.fn_index[fnid] |
71 | task_deps = dataCache.task_deps[fn] | 99 | task_deps = self.dataCache.task_deps[fn] |
72 | 100 | ||
73 | if fnid not in taskData.failed_fnids: | 101 | if fnid not in taskData.failed_fnids: |
74 | 102 | ||
@@ -94,6 +122,15 @@ class RunQueue: | |||
94 | dep = taskData.fn_index[depdata] | 122 | dep = taskData.fn_index[depdata] |
95 | depends.append(taskData.gettask_id(dep, taskname)) | 123 | depends.append(taskData.gettask_id(dep, taskname)) |
96 | 124 | ||
125 | idepends = taskData.tasks_idepends[task] | ||
126 | for idepend in idepends: | ||
127 | depid = int(idepend.split(":")[0]) | ||
128 | if depid in taskData.build_targets: | ||
129 | depdata = taskData.build_targets[depid][0] | ||
130 | if depdata: | ||
131 | dep = taskData.fn_index[depdata] | ||
132 | depends.append(taskData.gettask_id(dep, idepend.split(":")[1])) | ||
133 | |||
97 | def add_recursive_build(depid): | 134 | def add_recursive_build(depid): |
98 | """ | 135 | """ |
99 | Add build depends of depid to depends | 136 | Add build depends of depid to depends |
@@ -197,7 +234,7 @@ class RunQueue: | |||
197 | for depend in depends: | 234 | for depend in depends: |
198 | mark_active(depend, depth+1) | 235 | mark_active(depend, depth+1) |
199 | 236 | ||
200 | for target in targets: | 237 | for target in self.targets: |
201 | targetid = taskData.getbuild_id(target[0]) | 238 | targetid = taskData.getbuild_id(target[0]) |
202 | 239 | ||
203 | if targetid not in taskData.build_targets: | 240 | if targetid not in taskData.build_targets: |
@@ -209,10 +246,10 @@ class RunQueue: | |||
209 | fnid = taskData.build_targets[targetid][0] | 246 | fnid = taskData.build_targets[targetid][0] |
210 | 247 | ||
211 | # Remove stamps for targets if force mode active | 248 | # Remove stamps for targets if force mode active |
212 | if cooker.configuration.force: | 249 | if self.cooker.configuration.force: |
213 | fn = taskData.fn_index[fnid] | 250 | fn = taskData.fn_index[fnid] |
214 | bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (target[1], fn)) | 251 | bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (target[1], fn)) |
215 | bb.build.del_stamp(target[1], dataCache, fn) | 252 | bb.build.del_stamp(target[1], self.dataCache, fn) |
216 | 253 | ||
217 | if fnid in taskData.failed_fnids: | 254 | if fnid in taskData.failed_fnids: |
218 | continue | 255 | continue |
@@ -299,18 +336,18 @@ class RunQueue: | |||
299 | seen.append(taskid) | 336 | seen.append(taskid) |
300 | for revdep in self.runq_revdeps[taskid]: | 337 | for revdep in self.runq_revdeps[taskid]: |
301 | if runq_done[revdep] == 0 and revdep not in seen and not finish: | 338 | if runq_done[revdep] == 0 and revdep not in seen and not finish: |
302 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) (depends: %s)" % (revdep, self.get_user_idstring(revdep, taskData), self.runq_depends[revdep])) | 339 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) (depends: %s)" % (revdep, self.get_user_idstring(revdep), self.runq_depends[revdep])) |
303 | if revdep in deps_seen: | 340 | if revdep in deps_seen: |
304 | bb.msg.error(bb.msg.domain.RunQueue, "Chain ends at Task %s (%s)" % (revdep, self.get_user_idstring(revdep, taskData))) | 341 | bb.msg.error(bb.msg.domain.RunQueue, "Chain ends at Task %s (%s)" % (revdep, self.get_user_idstring(revdep))) |
305 | finish = True | 342 | finish = True |
306 | return | 343 | return |
307 | for dep in self.runq_depends[revdep]: | 344 | for dep in self.runq_depends[revdep]: |
308 | deps_seen.append(dep) | 345 | deps_seen.append(dep) |
309 | print_chain(revdep, finish) | 346 | print_chain(revdep, finish) |
310 | print_chain(task, False) | 347 | print_chain(task, False) |
311 | bb.msg.fatal(bb.msg.domain.RunQueue, "Task %s (%s) not processed!\nThis is probably a circular dependency (the chain might be printed above)." % (task, self.get_user_idstring(task, taskData))) | 348 | bb.msg.fatal(bb.msg.domain.RunQueue, "Task %s (%s) not processed!\nThis is probably a circular dependency (the chain might be printed above)." % (task, self.get_user_idstring(task))) |
312 | if runq_weight1[task] != 0: | 349 | if runq_weight1[task] != 0: |
313 | bb.msg.fatal(bb.msg.domain.RunQueue, "Task %s (%s) count not zero!" % (task, self.get_user_idstring(task, taskData))) | 350 | bb.msg.fatal(bb.msg.domain.RunQueue, "Task %s (%s) count not zero!" % (task, self.get_user_idstring(task))) |
314 | 351 | ||
315 | # Make a weight sorted map | 352 | # Make a weight sorted map |
316 | from copy import deepcopy | 353 | from copy import deepcopy |
@@ -328,7 +365,7 @@ class RunQueue: | |||
328 | 365 | ||
329 | #self.dump_data(taskData) | 366 | #self.dump_data(taskData) |
330 | 367 | ||
331 | def execute_runqueue(self, cooker, cfgData, dataCache, taskData, runlist): | 368 | def execute_runqueue(self): |
332 | """ | 369 | """ |
333 | Run the tasks in a queue prepared by prepare_runqueue | 370 | Run the tasks in a queue prepared by prepare_runqueue |
334 | Upon failure, optionally try to recover the build using any alternate providers | 371 | Upon failure, optionally try to recover the build using any alternate providers |
@@ -337,35 +374,86 @@ class RunQueue: | |||
337 | 374 | ||
338 | failures = 0 | 375 | failures = 0 |
339 | while 1: | 376 | while 1: |
340 | failed_fnids = self.execute_runqueue_internal(cooker, cfgData, dataCache, taskData) | 377 | failed_fnids = [] |
378 | try: | ||
379 | self.execute_runqueue_internal() | ||
380 | finally: | ||
381 | if self.master_process: | ||
382 | failed_fnids = self.finish_runqueue() | ||
341 | if len(failed_fnids) == 0: | 383 | if len(failed_fnids) == 0: |
342 | return failures | 384 | return failures |
343 | if taskData.abort: | 385 | if self.taskData.abort: |
344 | raise bb.runqueue.TaskFailure(failed_fnids) | 386 | raise bb.runqueue.TaskFailure(failed_fnids) |
345 | for fnid in failed_fnids: | 387 | for fnid in failed_fnids: |
346 | #print "Failure: %s %s %s" % (fnid, taskData.fn_index[fnid], self.runq_task[fnid]) | 388 | #print "Failure: %s %s %s" % (fnid, self.taskData.fn_index[fnid], self.runq_task[fnid]) |
347 | taskData.fail_fnid(fnid) | 389 | self.taskData.fail_fnid(fnid) |
348 | failures = failures + 1 | 390 | failures = failures + 1 |
349 | self.reset_runqueue() | 391 | self.reset_runqueue() |
350 | self.prepare_runqueue(cooker, cfgData, dataCache, taskData, runlist) | 392 | self.prepare_runqueue() |
393 | |||
394 | def execute_runqueue_initVars(self): | ||
395 | |||
396 | self.stats = RunQueueStats() | ||
397 | |||
398 | self.active_builds = 0 | ||
399 | self.runq_buildable = [] | ||
400 | self.runq_running = [] | ||
401 | self.runq_complete = [] | ||
402 | self.build_pids = {} | ||
403 | self.failed_fnids = [] | ||
404 | self.master_process = True | ||
351 | 405 | ||
352 | def execute_runqueue_internal(self, cooker, cfgData, dataCache, taskData): | 406 | # Mark initial buildable tasks |
407 | for task in range(len(self.runq_fnid)): | ||
408 | self.runq_running.append(0) | ||
409 | self.runq_complete.append(0) | ||
410 | if len(self.runq_depends[task]) == 0: | ||
411 | self.runq_buildable.append(1) | ||
412 | else: | ||
413 | self.runq_buildable.append(0) | ||
414 | |||
415 | def task_complete(self, task): | ||
416 | """ | ||
417 | Mark a task as completed | ||
418 | Look at the reverse dependencies and mark any task with | ||
419 | completed dependencies as buildable | ||
420 | """ | ||
421 | self.runq_complete[task] = 1 | ||
422 | for revdep in self.runq_revdeps[task]: | ||
423 | if self.runq_running[revdep] == 1: | ||
424 | continue | ||
425 | if self.runq_buildable[revdep] == 1: | ||
426 | continue | ||
427 | alldeps = 1 | ||
428 | for dep in self.runq_depends[revdep]: | ||
429 | if self.runq_complete[dep] != 1: | ||
430 | alldeps = 0 | ||
431 | if alldeps == 1: | ||
432 | self.runq_buildable[revdep] = 1 | ||
433 | fn = self.taskData.fn_index[self.runq_fnid[revdep]] | ||
434 | taskname = self.runq_task[revdep] | ||
435 | bb.msg.debug(1, bb.msg.domain.RunQueue, "Marking task %s (%s, %s) as buildable" % (revdep, fn, taskname)) | ||
436 | |||
437 | def get_next_task(self): | ||
438 | """ | ||
439 | Return the id of the highest priority task that is buildable | ||
440 | """ | ||
441 | for task1 in range(len(self.runq_fnid)): | ||
442 | task = self.prio_map[task1] | ||
443 | if self.runq_running[task] == 1: | ||
444 | continue | ||
445 | if self.runq_buildable[task] == 1: | ||
446 | return task | ||
447 | return None | ||
448 | |||
449 | def execute_runqueue_internal(self): | ||
353 | """ | 450 | """ |
354 | Run the tasks in a queue prepared by prepare_runqueue | 451 | Run the tasks in a queue prepared by prepare_runqueue |
355 | """ | 452 | """ |
356 | import signal | ||
357 | 453 | ||
358 | bb.msg.note(1, bb.msg.domain.RunQueue, "Executing runqueue") | 454 | bb.msg.note(1, bb.msg.domain.RunQueue, "Executing runqueue") |
359 | 455 | ||
360 | active_builds = 0 | 456 | self.execute_runqueue_initVars() |
361 | tasks_completed = 0 | ||
362 | tasks_skipped = 0 | ||
363 | |||
364 | runq_buildable = [] | ||
365 | runq_running = [] | ||
366 | runq_complete = [] | ||
367 | build_pids = {} | ||
368 | failed_fnids = [] | ||
369 | 457 | ||
370 | if len(self.runq_fnid) == 0: | 458 | if len(self.runq_fnid) == 0: |
371 | # nothing to do | 459 | # nothing to do |
@@ -374,144 +462,103 @@ class RunQueue: | |||
374 | def sigint_handler(signum, frame): | 462 | def sigint_handler(signum, frame): |
375 | raise KeyboardInterrupt | 463 | raise KeyboardInterrupt |
376 | 464 | ||
377 | def get_next_task(data): | 465 | while True: |
378 | """ | 466 | task = self.get_next_task() |
379 | Return the id of the highest priority task that is buildable | 467 | if task is not None: |
380 | """ | 468 | fn = self.taskData.fn_index[self.runq_fnid[task]] |
381 | for task1 in range(len(data.runq_fnid)): | 469 | |
382 | task = data.prio_map[task1] | 470 | taskname = self.runq_task[task] |
383 | if runq_running[task] == 1: | 471 | if bb.build.stamp_is_current(taskname, self.dataCache, fn): |
472 | bb.msg.debug(2, bb.msg.domain.RunQueue, "Stamp current task %s (%s)" % (task, self.get_user_idstring(task))) | ||
473 | self.runq_running[task] = 1 | ||
474 | self.task_complete(task) | ||
475 | self.stats.taskCompleted() | ||
476 | self.stats.taskSkipped() | ||
384 | continue | 477 | continue |
385 | if runq_buildable[task] == 1: | ||
386 | return task | ||
387 | return None | ||
388 | 478 | ||
389 | def task_complete(data, task): | 479 | bb.msg.note(1, bb.msg.domain.RunQueue, "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.active_builds + 1, len(self.runq_fnid), task, self.get_user_idstring(task))) |
390 | """ | 480 | try: |
391 | Mark a task as completed | 481 | pid = os.fork() |
392 | Look at the reverse dependencies and mark any task with | 482 | except OSError, e: |
393 | completed dependencies as buildable | 483 | bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) |
394 | """ | 484 | if pid == 0: |
395 | runq_complete[task] = 1 | 485 | # Bypass master process' handling |
396 | for revdep in data.runq_revdeps[task]: | 486 | self.master_process = False |
397 | if runq_running[revdep] == 1: | 487 | # Stop Ctrl+C being sent to children |
398 | continue | 488 | # signal.signal(signal.SIGINT, signal.SIG_IGN) |
399 | if runq_buildable[revdep] == 1: | 489 | # Make the child the process group leader |
490 | os.setpgid(0, 0) | ||
491 | sys.stdin = open('/dev/null', 'r') | ||
492 | self.cooker.configuration.cmd = taskname[3:] | ||
493 | try: | ||
494 | self.cooker.tryBuild(fn, False) | ||
495 | except bb.build.EventException: | ||
496 | bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") | ||
497 | sys.exit(1) | ||
498 | except: | ||
499 | bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") | ||
500 | raise | ||
501 | sys.exit(0) | ||
502 | self.build_pids[pid] = task | ||
503 | self.runq_running[task] = 1 | ||
504 | self.active_builds = self.active_builds + 1 | ||
505 | if self.active_builds < self.number_tasks: | ||
400 | continue | 506 | continue |
401 | alldeps = 1 | 507 | if self.active_builds > 0: |
402 | for dep in data.runq_depends[revdep]: | 508 | result = os.waitpid(-1, 0) |
403 | if runq_complete[dep] != 1: | 509 | self.active_builds = self.active_builds - 1 |
404 | alldeps = 0 | 510 | task = self.build_pids[result[0]] |
405 | if alldeps == 1: | 511 | if result[1] != 0: |
406 | runq_buildable[revdep] = 1 | 512 | del self.build_pids[result[0]] |
407 | fn = taskData.fn_index[self.runq_fnid[revdep]] | 513 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task))) |
408 | taskname = self.runq_task[revdep] | 514 | self.failed_fnids.append(self.runq_fnid[task]) |
409 | bb.msg.debug(1, bb.msg.domain.RunQueue, "Marking task %s (%s, %s) as buildable" % (revdep, fn, taskname)) | 515 | self.stats.taskFailed() |
410 | 516 | break | |
411 | # Mark initial buildable tasks | 517 | self.task_complete(task) |
412 | for task in range(len(self.runq_fnid)): | 518 | self.stats.taskCompleted() |
413 | runq_running.append(0) | 519 | del self.build_pids[result[0]] |
414 | runq_complete.append(0) | 520 | continue |
415 | if len(self.runq_depends[task]) == 0: | 521 | return |
416 | runq_buildable.append(1) | ||
417 | else: | ||
418 | runq_buildable.append(0) | ||
419 | |||
420 | |||
421 | number_tasks = int(bb.data.getVar("BB_NUMBER_THREADS", cfgData) or 1) | ||
422 | 522 | ||
523 | def finish_runqueue(self): | ||
423 | try: | 524 | try: |
424 | while 1: | 525 | while self.active_builds > 0: |
425 | task = get_next_task(self) | 526 | bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % self.active_builds) |
426 | if task is not None: | 527 | tasknum = 1 |
427 | fn = taskData.fn_index[self.runq_fnid[task]] | 528 | for k, v in self.build_pids.iteritems(): |
428 | taskname = self.runq_task[task] | 529 | bb.msg.note(1, bb.msg.domain.RunQueue, "%s: %s (%s)" % (tasknum, self.get_user_idstring(v), k)) |
429 | 530 | tasknum = tasknum + 1 | |
430 | if bb.build.stamp_is_current(taskname, dataCache, fn): | 531 | result = os.waitpid(-1, 0) |
431 | bb.msg.debug(2, bb.msg.domain.RunQueue, "Stamp current task %s (%s)" % (task, self.get_user_idstring(task, taskData))) | 532 | task = self.build_pids[result[0]] |
432 | runq_running[task] = 1 | 533 | if result[1] != 0: |
433 | task_complete(self, task) | 534 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task))) |
434 | tasks_completed = tasks_completed + 1 | 535 | self.failed_fnids.append(self.runq_fnid[task]) |
435 | tasks_skipped = tasks_skipped + 1 | 536 | self.stats.taskFailed() |
436 | continue | 537 | del self.build_pids[result[0]] |
437 | 538 | self.active_builds = self.active_builds - 1 | |
438 | bb.msg.note(1, bb.msg.domain.RunQueue, "Running task %d of %d (ID: %s, %s)" % (tasks_completed + active_builds + 1, len(self.runq_fnid), task, self.get_user_idstring(task, taskData))) | 539 | if len(self.failed_fnids) > 0: |
439 | try: | 540 | return self.failed_fnids |
440 | pid = os.fork() | 541 | except KeyboardInterrupt: |
441 | except OSError, e: | 542 | bb.msg.note(1, bb.msg.domain.RunQueue, "Sending SIGINT to remaining %s tasks" % self.active_builds) |
442 | bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) | 543 | for k, v in self.build_pids.iteritems(): |
443 | if pid == 0: | 544 | try: |
444 | # Bypass finally below | ||
445 | active_builds = 0 | ||
446 | # Stop Ctrl+C being sent to children | ||
447 | # signal.signal(signal.SIGINT, signal.SIG_IGN) | ||
448 | # Make the child the process group leader | ||
449 | os.setpgid(0, 0) | ||
450 | sys.stdin = open('/dev/null', 'r') | ||
451 | cooker.configuration.cmd = taskname[3:] | ||
452 | try: | ||
453 | cooker.tryBuild(fn, False) | ||
454 | except bb.build.EventException: | ||
455 | bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") | ||
456 | sys.exit(1) | ||
457 | except: | ||
458 | bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") | ||
459 | raise | ||
460 | sys.exit(0) | ||
461 | build_pids[pid] = task | ||
462 | runq_running[task] = 1 | ||
463 | active_builds = active_builds + 1 | ||
464 | if active_builds < number_tasks: | ||
465 | continue | ||
466 | if active_builds > 0: | ||
467 | result = os.waitpid(-1, 0) | ||
468 | active_builds = active_builds - 1 | ||
469 | task = build_pids[result[0]] | ||
470 | if result[1] != 0: | ||
471 | del build_pids[result[0]] | ||
472 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task, taskData))) | ||
473 | failed_fnids.append(self.runq_fnid[task]) | ||
474 | break | ||
475 | task_complete(self, task) | ||
476 | tasks_completed = tasks_completed + 1 | ||
477 | del build_pids[result[0]] | ||
478 | continue | ||
479 | break | ||
480 | finally: | ||
481 | try: | ||
482 | while active_builds > 0: | ||
483 | bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % active_builds) | ||
484 | tasknum = 1 | ||
485 | for k, v in build_pids.iteritems(): | ||
486 | bb.msg.note(1, bb.msg.domain.RunQueue, "%s: %s (%s)" % (tasknum, self.get_user_idstring(v, taskData), k)) | ||
487 | tasknum = tasknum + 1 | ||
488 | result = os.waitpid(-1, 0) | ||
489 | task = build_pids[result[0]] | ||
490 | if result[1] != 0: | ||
491 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task, taskData))) | ||
492 | failed_fnids.append(self.runq_fnid[task]) | ||
493 | del build_pids[result[0]] | ||
494 | active_builds = active_builds - 1 | ||
495 | if len(failed_fnids) > 0: | ||
496 | return failed_fnids | ||
497 | except: | ||
498 | bb.msg.note(1, bb.msg.domain.RunQueue, "Sending SIGINT to remaining %s tasks" % active_builds) | ||
499 | for k, v in build_pids.iteritems(): | ||
500 | os.kill(-k, signal.SIGINT) | 545 | os.kill(-k, signal.SIGINT) |
501 | raise | 546 | except: |
547 | pass | ||
548 | raise | ||
502 | 549 | ||
503 | # Sanity Checks | 550 | # Sanity Checks |
504 | for task in range(len(self.runq_fnid)): | 551 | for task in range(len(self.runq_fnid)): |
505 | if runq_buildable[task] == 0: | 552 | if self.runq_buildable[task] == 0: |
506 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s never buildable!" % task) | 553 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s never buildable!" % task) |
507 | if runq_running[task] == 0: | 554 | if self.runq_running[task] == 0: |
508 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s never ran!" % task) | 555 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s never ran!" % task) |
509 | if runq_complete[task] == 0: | 556 | if self.runq_complete[task] == 0: |
510 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s never completed!" % task) | 557 | bb.msg.error(bb.msg.domain.RunQueue, "Task %s never completed!" % task) |
511 | 558 | ||
512 | bb.msg.note(1, bb.msg.domain.RunQueue, "Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and %d failed." % (tasks_completed, tasks_skipped, len(failed_fnids))) | 559 | bb.msg.note(1, bb.msg.domain.RunQueue, "Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and %d failed." % (self.stats.completed, self.stats.skipped, self.stats.failed)) |
513 | 560 | ||
514 | return failed_fnids | 561 | return self.failed_fnids |
515 | 562 | ||
516 | def dump_data(self, taskQueue): | 563 | def dump_data(self, taskQueue): |
517 | """ | 564 | """ |