autotestd_monitor revision e8e73c6c1160fbd238172820ed5cb87da278e7ba
1#!/usr/bin/python 2 3import common 4import sys, os, signal, time, subprocess, fcntl 5 6logdir = sys.argv[1] 7stdout_start = int(sys.argv[2]) # number of bytes we can skip on stdout 8stderr_start = int(sys.argv[3]) # nubmer of bytes we can skip on stderr 9 10devnull = open(os.devnull, 'w') 11 12# launch some tail processes to pump the std* streams 13def launch_tail(filename, outstream, start): 14 path = os.path.join(logdir, filename) 15 argv = ['tail', '--retry', '--follow=name', '--bytes=+%d' % start, path] 16 # stdout=sys.stdout fails on pre-2.5 python (bug in subprocess module) 17 if outstream != subprocess.PIPE and outstream.fileno() == 1: 18 return subprocess.Popen(argv, stderr=devnull) 19 else: 20 return subprocess.Popen(argv, stdout=outstream, stderr=devnull) 21stdout_pump = launch_tail('stdout', sys.stdout, stdout_start) 22stderr_pump = launch_tail('stderr', sys.stderr, stderr_start) 23 24# wait for logdir/started to exist to be sure autotestd is started 25start_time = time.time() 26started_file_path = os.path.join(logdir, 'started') 27while not os.path.exists(started_file_path): 28 time.sleep(1) 29 if time.time() - start_time >= 30: 30 raise Exception("autotestd failed to start in %s" % logdir) 31os.remove(started_file_path) 32 33# watch the exit code file for an exit 34exit_code_file = open(os.path.join(logdir, 'exit_code')) 35fcntl.flock(exit_code_file, fcntl.LOCK_EX) 36try: 37 exit_code = exit_code_file.read() 38 if len(exit_code) != 4: 39 exit_code = -signal.SIGKILL # autotestd was nuked 40 else: 41 exit_code = int(exit_code) 42finally: 43 fcntl.flock(exit_code_file, fcntl.LOCK_UN) 44 exit_code_file.close() 45 46time.sleep(2) # tail runs in 1s polling loop, so give them a chance to finish 47os.kill(stdout_pump.pid, signal.SIGTERM) 48os.kill(stderr_pump.pid, signal.SIGTERM) 49 50# exit (with the same code as autotestd) 51sys.exit(exit_code) 52