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