1#! /usr/bin/env python3 2# 3# Copyright (C) 2020 Joshua Watt <JPEWhacker@gmail.com> 4# 5# SPDX-License-Identifier: MIT 6 7import argparse 8import os 9import random 10import shutil 11import signal 12import subprocess 13import sys 14import time 15 16 17def try_unlink(path): 18 try: 19 os.unlink(path) 20 except: 21 pass 22 23 24def main(): 25 def cleanup(): 26 shutil.rmtree("tmp/cache", ignore_errors=True) 27 try_unlink("bitbake-cookerdaemon.log") 28 try_unlink("bitbake.sock") 29 try_unlink("bitbake.lock") 30 31 parser = argparse.ArgumentParser( 32 description="Bitbake parser torture test", 33 epilog=""" 34 A torture test for bitbake's parser. Repeatedly interrupts parsing until 35 bitbake decides to deadlock. 36 """, 37 ) 38 39 args = parser.parse_args() 40 41 if not "BUILDDIR" in os.environ: 42 print( 43 "'BUILDDIR' not found in the environment. Did you initialize the build environment?" 44 ) 45 return 1 46 47 os.chdir(os.environ["BUILDDIR"]) 48 49 run_num = 0 50 while True: 51 if run_num % 100 == 0: 52 print("Calibrating wait time...") 53 cleanup() 54 55 start_time = time.monotonic() 56 r = subprocess.run(["bitbake", "-p"]) 57 max_wait_time = time.monotonic() - start_time 58 59 if r.returncode != 0: 60 print("Calibration run exited with %d" % r.returncode) 61 return 1 62 63 print("Maximum wait time is %f seconds" % max_wait_time) 64 65 run_num += 1 66 wait_time = random.random() * max_wait_time 67 68 print("Run #%d" % run_num) 69 print("Will sleep for %f seconds" % wait_time) 70 71 cleanup() 72 with subprocess.Popen(["bitbake", "-p"]) as proc: 73 time.sleep(wait_time) 74 proc.send_signal(signal.SIGINT) 75 try: 76 proc.wait(45) 77 except subprocess.TimeoutExpired: 78 print("Run #%d: Waited too long. Possible deadlock!" % run_num) 79 proc.wait() 80 return 1 81 82 if proc.returncode == 0: 83 print("Exited successfully. Timeout too long?") 84 else: 85 print("Exited with %d" % proc.returncode) 86 87 88if __name__ == "__main__": 89 sys.exit(main()) 90