summaryrefslogtreecommitdiffstats
path: root/bitbake/bin/bitbake-worker
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2015-09-29 09:28:24 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-10-01 07:43:38 +0100
commit1e467b333fe164a71404f3e3f6974440ce00e90f (patch)
tree781cb96d168c2734ff2e2b57ba9383c8cfadbea7 /bitbake/bin/bitbake-worker
parente5b9c2a9f2b9ad354d246b20d7252957dd5ebb42 (diff)
downloadpoky-1e467b333fe164a71404f3e3f6974440ce00e90f.tar.gz
bitbake: bitbake-worker: Guard against multiprocessing corruption of event data
In the forked child, we may use multiprocessing. There is only one event pipe to the worker controlling process and if we're unlucky, multiple processes can write to it at once corrupting the data by intermixing it. We don't see this often but when we do, its quite puzzling. I suspect it only happens in tasks which use multiprocessng (do_rootfs, do_package) and is much more likely to happen when we have long messages, usually many times PAGE_SIZE since PAGE_SIZE writes are atomic. This makes it much more likely within do_roofs, when for example a subprocess lists the contents of a rootfs. To fix this, we give each child a Lock() object and use this to serialise writes to the controlling worker. (Bitbake rev: 3cb55bdf06148943960e438291f9a562857340a3) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/bin/bitbake-worker')
-rwxr-xr-xbitbake/bin/bitbake-worker9
1 files changed, 9 insertions, 0 deletions
diff --git a/bitbake/bin/bitbake-worker b/bitbake/bin/bitbake-worker
index af17b874aa..3390f637e3 100755
--- a/bitbake/bin/bitbake-worker
+++ b/bitbake/bin/bitbake-worker
@@ -10,6 +10,7 @@ import bb
10import select 10import select
11import errno 11import errno
12import signal 12import signal
13from multiprocessing import Lock
13 14
14# Users shouldn't be running this code directly 15# Users shouldn't be running this code directly
15if len(sys.argv) != 2 or not sys.argv[1].startswith("decafbad"): 16if len(sys.argv) != 2 or not sys.argv[1].startswith("decafbad"):
@@ -44,6 +45,9 @@ except ImportError:
44 45
45worker_pipe = sys.stdout.fileno() 46worker_pipe = sys.stdout.fileno()
46bb.utils.nonblockingfd(worker_pipe) 47bb.utils.nonblockingfd(worker_pipe)
48# Need to guard against multiprocessing being used in child processes
49# and multiple processes trying to write to the parent at the same time
50worker_pipe_lock = None
47 51
48handler = bb.event.LogHandler() 52handler = bb.event.LogHandler()
49logger.addHandler(handler) 53logger.addHandler(handler)
@@ -85,10 +89,13 @@ def worker_flush():
85 89
86def worker_child_fire(event, d): 90def worker_child_fire(event, d):
87 global worker_pipe 91 global worker_pipe
92 global worker_pipe_lock
88 93
89 data = "<event>" + pickle.dumps(event) + "</event>" 94 data = "<event>" + pickle.dumps(event) + "</event>"
90 try: 95 try:
96 worker_pipe_lock.acquire()
91 worker_pipe.write(data) 97 worker_pipe.write(data)
98 worker_pipe_lock.release()
92 except IOError: 99 except IOError:
93 sigterm_handler(None, None) 100 sigterm_handler(None, None)
94 raise 101 raise
@@ -157,6 +164,7 @@ def fork_off_task(cfg, data, workerdata, fn, task, taskname, appends, taskdepdat
157 if pid == 0: 164 if pid == 0:
158 def child(): 165 def child():
159 global worker_pipe 166 global worker_pipe
167 global worker_pipe_lock
160 pipein.close() 168 pipein.close()
161 169
162 signal.signal(signal.SIGTERM, sigterm_handler) 170 signal.signal(signal.SIGTERM, sigterm_handler)
@@ -169,6 +177,7 @@ def fork_off_task(cfg, data, workerdata, fn, task, taskname, appends, taskdepdat
169 bb.event.worker_pid = os.getpid() 177 bb.event.worker_pid = os.getpid()
170 bb.event.worker_fire = worker_child_fire 178 bb.event.worker_fire = worker_child_fire
171 worker_pipe = pipeout 179 worker_pipe = pipeout
180 worker_pipe_lock = Lock()
172 181
173 # Make the child the process group leader and ensure no 182 # Make the child the process group leader and ensure no
174 # child process will be controlled by the current terminal 183 # child process will be controlled by the current terminal