123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- # Copyright 2020 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- """Workaround for qemu-img bug on arm64 platforms with multiple cores.
- Runs qemu-img command with timeout and retries the command if it hangs.
- See:
- crbug.com/1046861 QEMU is out of date; current version of qemu-img
- is unstable
- https://bugs.launchpad.net/qemu/+bug/1805256 qemu-img hangs on
- rcu_call_ready_event logic in Aarch64 when converting images
- TODO(crbug.com/1046861): Remove this workaround when the bug is fixed.
- """
- import logging
- import subprocess
- import tempfile
- import time
- # qemu-img p99 run time on Cavium ThunderX2 servers is 26 seconds.
- # Using 2x the p99 time as the timeout.
- QEMU_IMG_TIMEOUT_SEC = 52
- def _ExecQemuImgWithTimeout(command):
- """Execute qemu-img command in subprocess with timeout.
- Returns: None if command timed out or return code if command completed.
- """
- logging.info('qemu-img starting')
- command_output_file = tempfile.NamedTemporaryFile('w')
- p = subprocess.Popen(command, stdout=command_output_file,
- stderr=subprocess.STDOUT)
- start_sec = time.time()
- while p.poll() is None and time.time() - start_sec < QEMU_IMG_TIMEOUT_SEC:
- time.sleep(1)
- stop_sec = time.time()
- logging.info('qemu-img duration: %f' % float(stop_sec - start_sec))
- if p.poll() is None:
- returncode = None
- p.kill()
- p.wait()
- else:
- returncode = p.returncode
- log_level = logging.WARN if returncode else logging.DEBUG
- for line in open(command_output_file.name, 'r'):
- logging.log(log_level, 'qemu-img stdout: ' + line.strip())
- return returncode
- def ExecQemuImgWithRetry(command):
- """ Execute qemu-img command in subprocess with 2 retries.
- Raises CalledProcessError if command does not complete successfully.
- """
- tries = 0
- status = None
- while status is None and tries <= 2:
- tries += 1
- status = _ExecQemuImgWithTimeout(command)
- if status is None:
- raise subprocess.CalledProcessError(-1, command)
- if status:
- raise subprocess.CalledProcessError(status, command)
|