summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/runqueue.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/runqueue.py')
-rw-r--r--bitbake/lib/bb/runqueue.py187
1 files changed, 88 insertions, 99 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index 187720fc46..2b37619ae3 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -22,13 +22,12 @@ Handles preparation and execution of a queue of tasks
22# with this program; if not, write to the Free Software Foundation, Inc., 22# with this program; if not, write to the Free Software Foundation, Inc.,
23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 24
25import copy
25import os 26import os
26import sys 27import sys
27import subprocess
28import signal 28import signal
29import stat 29import stat
30import fcntl 30import fcntl
31import copy
32import logging 31import logging
33import bb 32import bb
34from bb import msg, data, event 33from bb import msg, data, event
@@ -36,12 +35,6 @@ from bb import msg, data, event
36bblogger = logging.getLogger("BitBake") 35bblogger = logging.getLogger("BitBake")
37logger = logging.getLogger("BitBake.RunQueue") 36logger = logging.getLogger("BitBake.RunQueue")
38 37
39try:
40 import cPickle as pickle
41except ImportError:
42 import pickle
43 logger.info("Importing cPickle failed. Falling back to a very slow implementation.")
44
45class RunQueueStats: 38class RunQueueStats:
46 """ 39 """
47 Holds statistics on the tasks handled by the associated runQueue 40 Holds statistics on the tasks handled by the associated runQueue
@@ -93,28 +86,28 @@ class RunQueueScheduler(object):
93 """ 86 """
94 self.rq = runqueue 87 self.rq = runqueue
95 self.rqdata = rqdata 88 self.rqdata = rqdata
96 numTasks = len(self.rq.runq_fnid) 89 numTasks = len(self.rqdata.runq_fnid)
97 90
98 self.prio_map = [] 91 self.prio_map = []
99 self.prio_map.extend(range(numTasks)) 92 self.prio_map.extend(range(numTasks))
100 93
101 def next_buildable_tasks(self): 94 def next_buildable_task(self):
102 """ 95 """
103 Return the id of the first task we find that is buildable 96 Return the id of the first task we find that is buildable
104 """ 97 """
105 for tasknum in range(len(self.rqdata.runq_fnid)): 98 for tasknum in xrange(len(self.rqdata.runq_fnid)):
106 taskid = self.prio_map[tasknum] 99 taskid = self.prio_map[tasknum]
107 if self.rq.runq_running[taskid] == 1: 100 if self.rq.runq_running[taskid] == 1:
108 continue 101 continue
109 if self.rq.runq_buildable[taskid] == 1: 102 if self.rq.runq_buildable[taskid] == 1:
110 yield taskid 103 return taskid
111 104
112 def next(self): 105 def next(self):
113 """ 106 """
114 Return the id of the task we should build next 107 Return the id of the task we should build next
115 """ 108 """
116 if self.rq.stats.active < self.rq.number_tasks: 109 if self.rq.stats.active < self.rq.number_tasks:
117 return next(self.next_buildable_tasks(), None) 110 return self.next_buildable_task()
118 111
119class RunQueueSchedulerSpeed(RunQueueScheduler): 112class RunQueueSchedulerSpeed(RunQueueScheduler):
120 """ 113 """
@@ -127,13 +120,12 @@ class RunQueueSchedulerSpeed(RunQueueScheduler):
127 """ 120 """
128 The priority map is sorted by task weight. 121 The priority map is sorted by task weight.
129 """ 122 """
130 from copy import deepcopy
131 123
132 self.rq = runqueue 124 self.rq = runqueue
133 self.rqdata = rqdata 125 self.rqdata = rqdata
134 126
135 sortweight = sorted(deepcopy(self.rqdata.runq_weight)) 127 sortweight = sorted(copy.deepcopy(self.rqdata.runq_weight))
136 copyweight = deepcopy(self.rqdata.runq_weight) 128 copyweight = copy.deepcopy(self.rqdata.runq_weight)
137 self.prio_map = [] 129 self.prio_map = []
138 130
139 for weight in sortweight: 131 for weight in sortweight:
@@ -155,12 +147,11 @@ class RunQueueSchedulerCompletion(RunQueueSchedulerSpeed):
155 147
156 def __init__(self, runqueue, rqdata): 148 def __init__(self, runqueue, rqdata):
157 RunQueueSchedulerSpeed.__init__(self, runqueue, rqdata) 149 RunQueueSchedulerSpeed.__init__(self, runqueue, rqdata)
158 from copy import deepcopy
159 150
160 #FIXME - whilst this groups all fnids together it does not reorder the 151 #FIXME - whilst this groups all fnids together it does not reorder the
161 #fnid groups optimally. 152 #fnid groups optimally.
162 153
163 basemap = deepcopy(self.prio_map) 154 basemap = copy.deepcopy(self.prio_map)
164 self.prio_map = [] 155 self.prio_map = []
165 while (len(basemap) > 0): 156 while (len(basemap) > 0):
166 entry = basemap.pop(0) 157 entry = basemap.pop(0)
@@ -190,25 +181,6 @@ class RunQueueData:
190 self.stampwhitelist = bb.data.getVar("BB_STAMP_WHITELIST", cfgData, 1) or "" 181 self.stampwhitelist = bb.data.getVar("BB_STAMP_WHITELIST", cfgData, 1) or ""
191 self.multi_provider_whitelist = (bb.data.getVar("MULTI_PROVIDER_WHITELIST", cfgData, 1) or "").split() 182 self.multi_provider_whitelist = (bb.data.getVar("MULTI_PROVIDER_WHITELIST", cfgData, 1) or "").split()
192 183
193 self.schedulers = set(obj for obj in globals().itervalues()
194 if type(obj) is type and issubclass(obj, RunQueueScheduler))
195
196 user_schedulers = bb.data.getVar("BB_SCHEDULERS", cfgData, True)
197 if user_schedulers:
198 for sched in user_schedulers.split():
199 if not "." in sched:
200 bb.note("Ignoring scheduler '%s' from BB_SCHEDULERS: not an import" % sched)
201 continue
202
203 modname, name = sched.rsplit(".", 1)
204 try:
205 module = __import__(modname, fromlist=(name,))
206 except ImportError, exc:
207 logger.critical("Unable to import scheduler '%s' from '%s': %s" % (name, modname, exc))
208 raise SystemExit(1)
209 else:
210 self.schedulers.add(getattr(module, name))
211
212 self.reset() 184 self.reset()
213 185
214 def reset(self): 186 def reset(self):
@@ -313,7 +285,7 @@ class RunQueueData:
313 if dep in explored_deps[revdep]: 285 if dep in explored_deps[revdep]:
314 scan = True 286 scan = True
315 if scan: 287 if scan:
316 find_chains(revdep, deepcopy(prev_chain)) 288 find_chains(revdep, copy.deepcopy(prev_chain))
317 for dep in explored_deps[revdep]: 289 for dep in explored_deps[revdep]:
318 if dep not in total_deps: 290 if dep not in total_deps:
319 total_deps.append(dep) 291 total_deps.append(dep)
@@ -715,20 +687,15 @@ class RunQueueData:
715 stampfnwhitelist.append(fn) 687 stampfnwhitelist.append(fn)
716 self.stampfnwhitelist = stampfnwhitelist 688 self.stampfnwhitelist = stampfnwhitelist
717 689
718 #self.dump_data(taskData)
719
720 # Interate over the task list looking for tasks with a 'setscene' function 690 # Interate over the task list looking for tasks with a 'setscene' function
721
722 self.runq_setscene = [] 691 self.runq_setscene = []
723 for task in range(len(self.runq_fnid)): 692 for task in range(len(self.runq_fnid)):
724 setscene = taskData.gettask_id(self.taskData.fn_index[self.runq_fnid[task]], self.runq_task[task] + "_setscene", False) 693 setscene = taskData.gettask_id(self.taskData.fn_index[self.runq_fnid[task]], self.runq_task[task] + "_setscene", False)
725 if not setscene: 694 if not setscene:
726 continue 695 continue
727 #bb.note("Found setscene for %s %s" % (self.taskData.fn_index[self.runq_fnid[task]], self.runq_task[task]))
728 self.runq_setscene.append(task) 696 self.runq_setscene.append(task)
729 697
730 # Interate over the task list and call into the siggen code 698 # Interate over the task list and call into the siggen code
731
732 dealtwith = set() 699 dealtwith = set()
733 todeal = set(range(len(self.runq_fnid))) 700 todeal = set(range(len(self.runq_fnid)))
734 while len(todeal) > 0: 701 while len(todeal) > 0:
@@ -744,7 +711,7 @@ class RunQueueData:
744 hashdata = {} 711 hashdata = {}
745 hashdata["hashes"] = {} 712 hashdata["hashes"] = {}
746 hashdata["deps"] = {} 713 hashdata["deps"] = {}
747 for task in range(len(self.runq_fnid)): 714 for task in xrange(len(self.runq_fnid)):
748 hashdata["hashes"][self.taskData.fn_index[self.runq_fnid[task]] + "." + self.runq_task[task]] = self.runq_hash[task] 715 hashdata["hashes"][self.taskData.fn_index[self.runq_fnid[task]] + "." + self.runq_task[task]] = self.runq_hash[task]
749 deps = [] 716 deps = []
750 for dep in self.runq_depends[task]: 717 for dep in self.runq_depends[task]:
@@ -764,24 +731,24 @@ class RunQueueData:
764 Dump some debug information on the internal data structures 731 Dump some debug information on the internal data structures
765 """ 732 """
766 logger.debug(3, "run_tasks:") 733 logger.debug(3, "run_tasks:")
767 for task in range(len(self.rqdata.runq_task)): 734 for task in xrange(len(self.rqdata.runq_task)):
768 logger.debug(3, " (%s)%s - %s: %s Deps %s RevDeps %s" % (task, 735 logger.debug(3, " (%s)%s - %s: %s Deps %s RevDeps %s", task,
769 taskQueue.fn_index[self.rqdata.runq_fnid[task]], 736 taskQueue.fn_index[self.rqdata.runq_fnid[task]],
770 self.rqdata.runq_task[task], 737 self.rqdata.runq_task[task],
771 self.rqdata.runq_weight[task], 738 self.rqdata.runq_weight[task],
772 self.rqdata.runq_depends[task], 739 self.rqdata.runq_depends[task],
773 self.rqdata.runq_revdeps[task])) 740 self.rqdata.runq_revdeps[task])
774 741
775 logger.debug(3, "sorted_tasks:") 742 logger.debug(3, "sorted_tasks:")
776 for task1 in range(len(self.rqdata.runq_task)): 743 for task1 in xrange(len(self.rqdata.runq_task)):
777 if task1 in self.prio_map: 744 if task1 in self.prio_map:
778 task = self.prio_map[task1] 745 task = self.prio_map[task1]
779 logger.debug(3, " (%s)%s - %s: %s Deps %s RevDeps %s" % (task, 746 logger.debug(3, " (%s)%s - %s: %s Deps %s RevDeps %s", task,
780 taskQueue.fn_index[self.rqdata.runq_fnid[task]], 747 taskQueue.fn_index[self.rqdata.runq_fnid[task]],
781 self.rqdata.runq_task[task], 748 self.rqdata.runq_task[task],
782 self.rqdata.runq_weight[task], 749 self.rqdata.runq_weight[task],
783 self.rqdata.runq_depends[task], 750 self.rqdata.runq_depends[task],
784 self.rqdata.runq_revdeps[task])) 751 self.rqdata.runq_revdeps[task])
785 752
786class RunQueue: 753class RunQueue:
787 def __init__(self, cooker, cfgData, dataCache, taskData, targets): 754 def __init__(self, cooker, cfgData, dataCache, taskData, targets):
@@ -809,7 +776,7 @@ class RunQueue:
809 if self.stamppolicy == "whitelist": 776 if self.stamppolicy == "whitelist":
810 stampwhitelist = self.rqdata.stampfnwhitelist 777 stampwhitelist = self.rqdata.stampfnwhitelist
811 778
812 for task in range(len(self.rqdata.runq_fnid)): 779 for task in xrange(len(self.rqdata.runq_fnid)):
813 unchecked[task] = "" 780 unchecked[task] = ""
814 if len(self.rqdata.runq_depends[task]) == 0: 781 if len(self.rqdata.runq_depends[task]) == 0:
815 buildable.append(task) 782 buildable.append(task)
@@ -824,7 +791,7 @@ class RunQueue:
824 if revdep in unchecked: 791 if revdep in unchecked:
825 buildable.append(revdep) 792 buildable.append(revdep)
826 793
827 for task in range(len(self.rqdata.runq_fnid)): 794 for task in xrange(len(self.rqdata.runq_fnid)):
828 if task not in unchecked: 795 if task not in unchecked:
829 continue 796 continue
830 fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]] 797 fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]]
@@ -909,7 +876,7 @@ class RunQueue:
909 fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]] 876 fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]]
910 if taskname is None: 877 if taskname is None:
911 taskname = self.rqdata.runq_task[task] 878 taskname = self.rqdata.runq_task[task]
912 879
913 stampfile = bb.parse.siggen.stampfile(self.rqdata.dataCache.stamp[fn], fn, taskname) 880 stampfile = bb.parse.siggen.stampfile(self.rqdata.dataCache.stamp[fn], fn, taskname)
914 881
915 # If the stamp is missing its not current 882 # If the stamp is missing its not current
@@ -919,7 +886,7 @@ class RunQueue:
919 # If its a 'nostamp' task, it's not current 886 # If its a 'nostamp' task, it's not current
920 taskdep = self.rqdata.dataCache.task_deps[fn] 887 taskdep = self.rqdata.dataCache.task_deps[fn]
921 if 'nostamp' in taskdep and taskname in taskdep['nostamp']: 888 if 'nostamp' in taskdep and taskname in taskdep['nostamp']:
922 logger.debug(2, "%s.%s is nostamp\n" % (fn, taskname)) 889 logger.debug(2, "%s.%s is nostamp\n", fn, taskname)
923 return False 890 return False
924 891
925 if taskname != "do_setscene" and taskname.endswith("_setscene"): 892 if taskname != "do_setscene" and taskname.endswith("_setscene"):
@@ -939,10 +906,10 @@ class RunQueue:
939 continue 906 continue
940 if fn == fn2 or (fulldeptree and fn2 not in stampwhitelist): 907 if fn == fn2 or (fulldeptree and fn2 not in stampwhitelist):
941 if not t2: 908 if not t2:
942 logger.debug(2, "Stampfile %s does not exist" % (stampfile2)) 909 logger.debug(2, 'Stampfile %s does not exist', stampfile2)
943 iscurrent = False 910 iscurrent = False
944 if t1 < t2: 911 if t1 < t2:
945 logger.debug(2, "Stampfile %s < %s" % (stampfile, stampfile2)) 912 logger.debug(2, 'Stampfile %s < %s', stampfile, stampfile2)
946 iscurrent = False 913 iscurrent = False
947 914
948 return iscurrent 915 return iscurrent
@@ -1014,7 +981,7 @@ class RunQueue:
1014 bb.note("Reparsing files to collect dependency data") 981 bb.note("Reparsing files to collect dependency data")
1015 for task in range(len(self.rqdata.runq_fnid)): 982 for task in range(len(self.rqdata.runq_fnid)):
1016 if self.rqdata.runq_fnid[task] not in done: 983 if self.rqdata.runq_fnid[task] not in done:
1017 fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]] 984 fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]]
1018 the_data = bb.cache.Cache.loadDataFull(fn, self.cooker.get_file_appends(fn), self.cooker.configuration.data) 985 the_data = bb.cache.Cache.loadDataFull(fn, self.cooker.get_file_appends(fn), self.cooker.configuration.data)
1019 done.add(self.rqdata.runq_fnid[task]) 986 done.add(self.rqdata.runq_fnid[task])
1020 987
@@ -1087,7 +1054,7 @@ class RunQueueExecute:
1087 self.rq.state = runQueueComplete 1054 self.rq.state = runQueueComplete
1088 return 1055 return
1089 1056
1090 def fork_off_task(self, fn, task, taskname): 1057 def fork_off_task(self, fn, task, taskname, quieterrors=False):
1091 the_data = bb.cache.Cache.loadDataFull(fn, self.cooker.get_file_appends(fn), self.cooker.configuration.data) 1058 the_data = bb.cache.Cache.loadDataFull(fn, self.cooker.get_file_appends(fn), self.cooker.configuration.data)
1092 1059
1093 env = bb.data.export_vars(the_data) 1060 env = bb.data.export_vars(the_data)
@@ -1115,10 +1082,9 @@ class RunQueueExecute:
1115 sys.stdout.flush() 1082 sys.stdout.flush()
1116 sys.stderr.flush() 1083 sys.stderr.flush()
1117 try: 1084 try:
1118 pipeinfd, pipeoutfd = os.pipe() 1085 pipein, pipeout = os.pipe()
1119 pipein = os.fdopen(pipeinfd, 'rb', 4096) 1086 pipein = os.fdopen(pipein, 'rb', 4096)
1120 pipeout = os.fdopen(pipeoutfd, 'wb', 4096) 1087 pipeout = os.fdopen(pipeout, 'wb', 0)
1121
1122 pid = os.fork() 1088 pid = os.fork()
1123 except OSError as e: 1089 except OSError as e:
1124 bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) 1090 bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror))
@@ -1148,7 +1114,7 @@ class RunQueueExecute:
1148 #newso = open(logout, 'w') 1114 #newso = open(logout, 'w')
1149 #os.dup2(newso.fileno(), sys.stdout.fileno()) 1115 #os.dup2(newso.fileno(), sys.stdout.fileno())
1150 #os.dup2(newso.fileno(), sys.stderr.fileno()) 1116 #os.dup2(newso.fileno(), sys.stderr.fileno())
1151 if taskname.endswith("_setscene"): 1117 if quieterrors:
1152 the_data.setVarFlag(taskname, "quieterrors", "1") 1118 the_data.setVarFlag(taskname, "quieterrors", "1")
1153 1119
1154 bb.data.setVar("BB_WORKERCONTEXT", "1", the_data) 1120 bb.data.setVar("BB_WORKERCONTEXT", "1", the_data)
@@ -1219,14 +1185,38 @@ class RunQueueExecuteTasks(RunQueueExecute):
1219 1185
1220 event.fire(bb.event.StampUpdate(self.rqdata.target_pairs, self.rqdata.dataCache.stamp), self.cfgData) 1186 event.fire(bb.event.StampUpdate(self.rqdata.target_pairs, self.rqdata.dataCache.stamp), self.cfgData)
1221 1187
1222 for scheduler in self.rqdata.schedulers: 1188 schedulers = self.get_schedulers()
1189 for scheduler in schedulers:
1223 if self.scheduler == scheduler.name: 1190 if self.scheduler == scheduler.name:
1224 self.sched = scheduler(self, self.rqdata) 1191 self.sched = scheduler(self, self.rqdata)
1225 logger.debug(1, "Using runqueue scheduler '%s'", scheduler.name) 1192 logger.debug(1, "Using runqueue scheduler '%s'", scheduler.name)
1226 break 1193 break
1227 else: 1194 else:
1228 bb.fatal("Invalid scheduler '%s'. Available schedulers: %s" % 1195 bb.fatal("Invalid scheduler '%s'. Available schedulers: %s" %
1229 (self.scheduler, ", ".join(obj.name for obj in self.rqdata.schedulers))) 1196 (self.scheduler, ", ".join(obj.name for obj in schedulers)))
1197
1198
1199 def get_schedulers(self):
1200 schedulers = set(obj for obj in globals().values()
1201 if type(obj) is type and
1202 issubclass(obj, RunQueueScheduler))
1203
1204 user_schedulers = bb.data.getVar("BB_SCHEDULERS", self.cfgData, True)
1205 if user_schedulers:
1206 for sched in user_schedulers.split():
1207 if not "." in sched:
1208 bb.note("Ignoring scheduler '%s' from BB_SCHEDULERS: not an import" % sched)
1209 continue
1210
1211 modname, name = sched.rsplit(".", 1)
1212 try:
1213 module = __import__(modname, fromlist=(name,))
1214 except ImportError, exc:
1215 logger.critical("Unable to import scheduler '%s' from '%s': %s" % (name, modname, exc))
1216 raise SystemExit(1)
1217 else:
1218 schedulers.add(getattr(module, name))
1219 return schedulers
1230 1220
1231 def task_completeoutright(self, task): 1221 def task_completeoutright(self, task):
1232 """ 1222 """
@@ -1283,17 +1273,17 @@ class RunQueueExecuteTasks(RunQueueExecute):
1283 # nothing to do 1273 # nothing to do
1284 self.rq.state = runQueueCleanUp 1274 self.rq.state = runQueueCleanUp
1285 1275
1286 for task in iter(self.sched.next, None): 1276 task = self.sched.next()
1277 if task is not None:
1287 fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]] 1278 fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]]
1288 1279
1289 taskname = self.rqdata.runq_task[task] 1280 taskname = self.rqdata.runq_task[task]
1290 if self.rq.check_stamp_task(task, taskname): 1281 if self.rq.check_stamp_task(task, taskname):
1291 logger.debug(2, "Stamp current task %s (%s)" % (task, self.rqdata.get_user_idstring(task))) 1282 logger.debug(2, "Stamp current task %s (%s)", task,
1283 self.rqdata.get_user_idstring(task))
1292 self.task_skip(task) 1284 self.task_skip(task)
1293 return True 1285 return True
1294 1286
1295 bb.event.fire(runQueueTaskStarted(task, self.stats, self.rq), self.cfgData)
1296
1297 taskdep = self.rqdata.dataCache.task_deps[fn] 1287 taskdep = self.rqdata.dataCache.task_deps[fn]
1298 if 'noexec' in taskdep and taskname in taskdep['noexec']: 1288 if 'noexec' in taskdep and taskname in taskdep['noexec']:
1299 startevent = runQueueTaskStarted(task, self.stats, self.rq, 1289 startevent = runQueueTaskStarted(task, self.stats, self.rq,
@@ -1457,12 +1447,11 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
1457 1447
1458 for task in xrange(len(self.sq_revdeps)): 1448 for task in xrange(len(self.sq_revdeps)):
1459 if task not in valid_new and task not in noexec: 1449 if task not in valid_new and task not in noexec:
1460 logger.debug(2, "No package found so skipping setscene task %s" % (self.rqdata.get_user_idstring(self.rqdata.runq_setscene[task]))) 1450 logger.debug(2, 'No package found, so skipping setscene task %s',
1451 self.rqdata.get_user_idstring(task))
1461 self.task_failoutright(task) 1452 self.task_failoutright(task)
1462 1453
1463 #print(str(valid)) 1454 logger.info('Executing SetScene Tasks')
1464
1465 logger.info("Executing SetScene Tasks")
1466 1455
1467 self.rq.state = runQueueSceneRun 1456 self.rq.state = runQueueSceneRun
1468 1457
@@ -1523,11 +1512,6 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
1523 # Find the next setscene to run 1512 # Find the next setscene to run
1524 for nexttask in xrange(self.stats.total): 1513 for nexttask in xrange(self.stats.total):
1525 if self.runq_buildable[nexttask] == 1 and self.runq_running[nexttask] != 1: 1514 if self.runq_buildable[nexttask] == 1 and self.runq_running[nexttask] != 1:
1526 #bb.note("Comparing %s to %s" % (self.sq_revdeps[nexttask], self.scenequeue_covered))
1527 #if len(self.sq_revdeps[nexttask]) > 0 and self.sq_revdeps[nexttask].issubset(self.scenequeue_covered):
1528 # bb.note("Skipping task %s" % nexttask)
1529 # self.scenequeue_skip(nexttask)
1530 # return True
1531 task = nexttask 1515 task = nexttask
1532 break 1516 break
1533 if task is not None: 1517 if task is not None:
@@ -1536,7 +1520,8 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
1536 1520
1537 taskname = self.rqdata.runq_task[realtask] + "_setscene" 1521 taskname = self.rqdata.runq_task[realtask] + "_setscene"
1538 if self.rq.check_stamp_task(realtask, self.rqdata.runq_task[realtask]): 1522 if self.rq.check_stamp_task(realtask, self.rqdata.runq_task[realtask]):
1539 logger.debug(2, "Stamp for underlying task %s (%s) is current so skipping setscene varient" % (task, self.rqdata.get_user_idstring(task))) 1523 logger.debug(2, 'Stamp for underlying task %s(%s) is current, so skipping setscene variant',
1524 task, self.rqdata.get_user_idstring(task))
1540 self.task_failoutright(task) 1525 self.task_failoutright(task)
1541 return True 1526 return True
1542 1527
@@ -1547,7 +1532,8 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
1547 return True 1532 return True
1548 1533
1549 if self.rq.check_stamp_task(realtask, taskname): 1534 if self.rq.check_stamp_task(realtask, taskname):
1550 logger.debug(2, "Setscene stamp current task %s (%s) so skip it and its dependencies" % (task, self.rqdata.get_user_idstring(realtask))) 1535 logger.debug(2, 'Setscene stamp current task %s(%s), so skip it and its dependencies',
1536 task, self.rqdata.get_user_idstring(realtask))
1551 self.task_skip(task) 1537 self.task_skip(task)
1552 return True 1538 return True
1553 1539
@@ -1577,11 +1563,14 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
1577 for task in oldcovered: 1563 for task in oldcovered:
1578 self.rq.scenequeue_covered.add(self.rqdata.runq_setscene[task]) 1564 self.rq.scenequeue_covered.add(self.rqdata.runq_setscene[task])
1579 1565
1580 bb.debug(1, "We can skip tasks %s" % self.rq.scenequeue_covered) 1566 logger.debug(1, 'We can skip tasks %s', self.rq.scenequeue_covered)
1581 1567
1582 self.rq.state = runQueueRunInit 1568 self.rq.state = runQueueRunInit
1583 return True 1569 return True
1584 1570
1571 def fork_off_task(self, fn, task, taskname):
1572 return RunQueueExecute.fork_off_task(self, fn, task, taskname, quieterrors=True)
1573
1585class TaskFailure(Exception): 1574class TaskFailure(Exception):
1586 """ 1575 """
1587 Exception raised when a task in a runqueue fails 1576 Exception raised when a task in a runqueue fails
@@ -1632,12 +1621,12 @@ class runQueueTaskCompleted(runQueueEvent):
1632 """ 1621 """
1633 1622
1634#def check_stamp_fn(fn, taskname, d): 1623#def check_stamp_fn(fn, taskname, d):
1635# rq = bb.data.getVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", d) 1624# rqexe = bb.data.getVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", d)
1636# fn = bb.data.getVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY2", d) 1625# fn = bb.data.getVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY2", d)
1637# fnid = rq.rqdata.taskData.getfn_id(fn) 1626# fnid = rqexe.rqdata.taskData.getfn_id(fn)
1638# taskid = rq.get_task_id(fnid, taskname) 1627# taskid = rqexe.rqdata.get_task_id(fnid, taskname)
1639# if taskid is not None: 1628# if taskid is not None:
1640# return rq.check_stamp_task(taskid) 1629# return rqexe.rq.check_stamp_task(taskid)
1641# return None 1630# return None
1642 1631
1643class runQueuePipe(): 1632class runQueuePipe():
@@ -1645,17 +1634,17 @@ class runQueuePipe():
1645 Abstraction for a pipe between a worker thread and the server 1634 Abstraction for a pipe between a worker thread and the server
1646 """ 1635 """
1647 def __init__(self, pipein, pipeout, d): 1636 def __init__(self, pipein, pipeout, d):
1648 self.fd = pipein 1637 self.input = pipein
1649 pipeout.close() 1638 pipeout.close()
1650 fcntl.fcntl(self.fd, fcntl.F_SETFL, fcntl.fcntl(self.fd, fcntl.F_GETFL) | os.O_NONBLOCK) 1639 fcntl.fcntl(self.input, fcntl.F_SETFL, fcntl.fcntl(self.input, fcntl.F_GETFL) | os.O_NONBLOCK)
1651 self.queue = "" 1640 self.queue = ""
1652 self.d = d 1641 self.d = d
1653 1642
1654 def read(self): 1643 def read(self):
1655 start = len(self.queue) 1644 start = len(self.queue)
1656 try: 1645 try:
1657 self.queue = self.queue + self.fd.read(1024) 1646 self.queue = self.queue + self.input.read(1024)
1658 except IOError: 1647 except (OSError, IOError):
1659 pass 1648 pass
1660 end = len(self.queue) 1649 end = len(self.queue)
1661 index = self.queue.find("</event>") 1650 index = self.queue.find("</event>")
@@ -1670,4 +1659,4 @@ class runQueuePipe():
1670 continue 1659 continue
1671 if len(self.queue) > 0: 1660 if len(self.queue) > 0:
1672 print("Warning, worker left partial message: %s" % self.queue) 1661 print("Warning, worker left partial message: %s" % self.queue)
1673 self.fd.close() 1662 self.input.close()