diff options
author | Chen Qi <Qi.Chen@windriver.com> | 2018-06-07 15:52:46 +0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2018-06-18 11:07:58 +0100 |
commit | 27061a274f47c72a2290182f7b1da6d6ec309fc7 (patch) | |
tree | 8f16fdcafd6f8212ae21613ec0c8c009c0f2253f /scripts/runqemu | |
parent | ffeb85ab80fb2f15d31675a0e6deddb1bab4760e (diff) | |
download | poky-27061a274f47c72a2290182f7b1da6d6ec309fc7.tar.gz |
runqemu: add SIGTERM handler to make sure things are cleaned up
Add SIGTERM handler so that runqemu could clean things up correctly
when receving such signal.
This problem was originally observed when running testimage. On
some hosts, after running testimage task, the user has to manually
operate on the tap interface (e.g. `sudo ip link del tap0') in order
for the next runqemu command to launch successfully.
The problem is about runqemu, SIGTERM and network manager on the host.
In testimage task, the runqemu process will receive SIGTERM. In such
situation, its cleanup() function is not run, resulting in tap interface
not cleaned up. On some hosts, the network manager will bring down the
tap interface automatically, thus this problem. I saw this problem on
Fedora21.
I think we'd better just clean up the tap interface ourselves.
So this patch adds to runqemu a SIGTERM handler, in which the actual
qemu process is terminated and other things cleaned up.
(From OE-Core rev: 02709d4709c56f9b9095e3555da35b659b03a8a3)
Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/runqemu')
-rwxr-xr-x | scripts/runqemu | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/scripts/runqemu b/scripts/runqemu index d998494063..de42d0f323 100755 --- a/scripts/runqemu +++ b/scripts/runqemu | |||
@@ -27,6 +27,7 @@ import fcntl | |||
27 | import shutil | 27 | import shutil |
28 | import glob | 28 | import glob |
29 | import configparser | 29 | import configparser |
30 | import signal | ||
30 | 31 | ||
31 | class RunQemuError(Exception): | 32 | class RunQemuError(Exception): |
32 | """Custom exception to raise on known errors.""" | 33 | """Custom exception to raise on known errors.""" |
@@ -233,6 +234,10 @@ class BaseConfig(object): | |||
233 | # slirp qemus are running. | 234 | # slirp qemus are running. |
234 | self.mac_tap = "52:54:00:12:34:" | 235 | self.mac_tap = "52:54:00:12:34:" |
235 | self.mac_slirp = "52:54:00:12:35:" | 236 | self.mac_slirp = "52:54:00:12:35:" |
237 | # pid of the actual qemu process | ||
238 | self.qemupid = None | ||
239 | # avoid cleanup twice | ||
240 | self.cleaned = False | ||
236 | 241 | ||
237 | def acquire_lock(self, error=True): | 242 | def acquire_lock(self, error=True): |
238 | logger.debug("Acquiring lockfile %s..." % self.lock) | 243 | logger.debug("Acquiring lockfile %s..." % self.lock) |
@@ -1200,10 +1205,18 @@ class BaseConfig(object): | |||
1200 | cmd = "%s %s" % (self.qemu_opt, kernel_opts) | 1205 | cmd = "%s %s" % (self.qemu_opt, kernel_opts) |
1201 | logger.info('Running %s\n' % cmd) | 1206 | logger.info('Running %s\n' % cmd) |
1202 | process = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE) | 1207 | process = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE) |
1208 | self.qemupid = process.pid | ||
1203 | if process.wait(): | 1209 | if process.wait(): |
1204 | logger.error("Failed to run qemu: %s", process.stderr.read().decode()) | 1210 | logger.error("Failed to run qemu: %s", process.stderr.read().decode()) |
1205 | 1211 | ||
1206 | def cleanup(self): | 1212 | def cleanup(self): |
1213 | if self.cleaned: | ||
1214 | return | ||
1215 | |||
1216 | # avoid dealing with SIGTERM when cleanup function is running | ||
1217 | signal.signal(signal.SIGTERM, signal.SIG_IGN) | ||
1218 | |||
1219 | logger.info("Cleaning up") | ||
1207 | if self.cleantap: | 1220 | if self.cleantap: |
1208 | cmd = 'sudo %s %s %s' % (self.qemuifdown, self.tap, self.bindir_native) | 1221 | cmd = 'sudo %s %s %s' % (self.qemuifdown, self.tap, self.bindir_native) |
1209 | logger.debug('Running %s' % cmd) | 1222 | logger.debug('Running %s' % cmd) |
@@ -1227,6 +1240,8 @@ class BaseConfig(object): | |||
1227 | shutil.rmtree(self.rootfs) | 1240 | shutil.rmtree(self.rootfs) |
1228 | shutil.rmtree('%s.pseudo_state' % self.rootfs) | 1241 | shutil.rmtree('%s.pseudo_state' % self.rootfs) |
1229 | 1242 | ||
1243 | self.cleaned = True | ||
1244 | |||
1230 | def load_bitbake_env(self, mach=None): | 1245 | def load_bitbake_env(self, mach=None): |
1231 | if self.bitbake_e: | 1246 | if self.bitbake_e: |
1232 | return | 1247 | return |
@@ -1282,6 +1297,13 @@ def main(): | |||
1282 | return 0 | 1297 | return 0 |
1283 | try: | 1298 | try: |
1284 | config = BaseConfig() | 1299 | config = BaseConfig() |
1300 | |||
1301 | def sigterm_handler(signum, frame): | ||
1302 | logger.info("SIGTERM received") | ||
1303 | os.kill(config.qemupid, signal.SIGTERM) | ||
1304 | config.cleanup() | ||
1305 | signal.signal(signal.SIGTERM, sigterm_handler) | ||
1306 | |||
1285 | config.check_args() | 1307 | config.check_args() |
1286 | config.read_qemuboot() | 1308 | config.read_qemuboot() |
1287 | config.check_and_set() | 1309 | config.check_and_set() |
@@ -1300,7 +1322,6 @@ def main(): | |||
1300 | traceback.print_exc() | 1322 | traceback.print_exc() |
1301 | return 1 | 1323 | return 1 |
1302 | finally: | 1324 | finally: |
1303 | print("Cleanup") | ||
1304 | config.cleanup() | 1325 | config.cleanup() |
1305 | 1326 | ||
1306 | if __name__ == "__main__": | 1327 | if __name__ == "__main__": |