diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-06-15 12:00:33 -1000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-06-19 17:06:18 +0100 |
commit | f46f6af1f255544e4399e0ce4aee6ce9061a259d (patch) | |
tree | e78e5d7b6d469b7cc02768718c6f5943a90e8432 | |
parent | aa2c6a789aa883f504465b9203f2e76e5859e9eb (diff) | |
download | poky-f46f6af1f255544e4399e0ce4aee6ce9061a259d.tar.gz |
bitbake: cooker: Avoid parser deadlocks
If you make parsing fail (e.g. add something like:
X := "${@d.getVar('MCMACHINES').split()[1]}"
to meson.bbclass, then run "while true; do bitbake -g bash; done"
it will eventually hang. It appears the cancel_join_thread() call the
parsing failure triggers, breaks the results_queue badly enough that it
sits in read() indefintely (called from self.result_queue.get(timeout=0.25)).
The timeout only applies to lock aquisition, not the read call.
I've tried various other approaches such as using cancel_join_thread()
in other places but the only way things don't lock up is to avoid
cancel_join_thread() entirely for results_queue.
I do have a concern that this may adversely affect Ctrl+C handling
but equally, its broken now already and this appears to improve
things.
[YOCTO #14034]
(Bitbake rev: 0e0af15b84e07e6763300dcd092b980086b9b9c4)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | bitbake/lib/bb/cooker.py | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py index 4d2c62cd96..730cdc56ff 100644 --- a/bitbake/lib/bb/cooker.py +++ b/bitbake/lib/bb/cooker.py | |||
@@ -1933,7 +1933,8 @@ class Parser(multiprocessing.Process): | |||
1933 | except queue.Empty: | 1933 | except queue.Empty: |
1934 | pass | 1934 | pass |
1935 | else: | 1935 | else: |
1936 | self.results.cancel_join_thread() | 1936 | self.results.close() |
1937 | self.results.join_thread() | ||
1937 | break | 1938 | break |
1938 | 1939 | ||
1939 | if pending: | 1940 | if pending: |
@@ -1942,6 +1943,8 @@ class Parser(multiprocessing.Process): | |||
1942 | try: | 1943 | try: |
1943 | job = self.jobs.pop() | 1944 | job = self.jobs.pop() |
1944 | except IndexError: | 1945 | except IndexError: |
1946 | self.results.close() | ||
1947 | self.results.join_thread() | ||
1945 | break | 1948 | break |
1946 | result = self.parse(*job) | 1949 | result = self.parse(*job) |
1947 | # Clear the siggen cache after parsing to control memory usage, its huge | 1950 | # Clear the siggen cache after parsing to control memory usage, its huge |
@@ -2060,8 +2063,6 @@ class CookerParser(object): | |||
2060 | 2063 | ||
2061 | bb.event.fire(event, self.cfgdata) | 2064 | bb.event.fire(event, self.cfgdata) |
2062 | 2065 | ||
2063 | # Allow data left in the cancel queue to be discarded | ||
2064 | self.parser_quit.cancel_join_thread() | ||
2065 | for process in self.processes: | 2066 | for process in self.processes: |
2066 | self.parser_quit.put(None) | 2067 | self.parser_quit.put(None) |
2067 | 2068 | ||
@@ -2081,7 +2082,8 @@ class CookerParser(object): | |||
2081 | process.join() | 2082 | process.join() |
2082 | 2083 | ||
2083 | self.parser_quit.close() | 2084 | self.parser_quit.close() |
2084 | self.parser_quit.join_thread() | 2085 | # Allow data left in the cancel queue to be discarded |
2086 | self.parser_quit.cancel_join_thread() | ||
2085 | 2087 | ||
2086 | sync = threading.Thread(target=self.bb_cache.sync) | 2088 | sync = threading.Thread(target=self.bb_cache.sync) |
2087 | self.syncthread = sync | 2089 | self.syncthread = sync |