Home | History | Annotate | Download | only in bin
      1 #!/usr/bin/python
      2 
      3 import common
      4 import sys, os, signal, time, subprocess, fcntl
      5 
      6 logdir = sys.argv[1]
      7 stdout_start = int(sys.argv[2])  # number of bytes we can skip on stdout
      8 stderr_start = int(sys.argv[3])  # nubmer of bytes we can skip on stderr
      9 # TODO (crosbug.com/38224)- sbasi: Remove extra logging.
     10 stderr = open(os.path.join(logdir, 'stderr'), 'a', 0)
     11 
     12 print >> stderr, 'Entered autotestd_monitor.'
     13 # if any of our tail processes die, the monitor should die too
     14 def kill_self(signum, frame):
     15     os.kill(os.getpid(), signal.SIGTERM)
     16 signal.signal(signal.SIGCHLD, kill_self)
     17 
     18 devnull = open(os.devnull, 'w')
     19 
     20 # launch some tail processes to pump the std* streams
     21 def launch_tail(filename, outstream, start):
     22     path = os.path.join(logdir, filename)
     23     argv = ['tail', '--retry', '--follow=name', '--bytes=+%d' % start, path]
     24     # stdout=sys.stdout fails on pre-2.5 python (bug in subprocess module)
     25     if outstream != subprocess.PIPE and outstream.fileno() == 1:
     26         return subprocess.Popen(argv, stderr=devnull)
     27     else:
     28         return subprocess.Popen(argv, stdout=outstream, stderr=devnull)
     29 stdout_pump = launch_tail('stdout', sys.stdout, stdout_start)
     30 stderr_pump = launch_tail('stderr', sys.stderr, stderr_start)
     31 
     32 print >> stderr, 'Finished launching tail subprocesses.'
     33 
     34 # wait for logdir/started to exist to be sure autotestd is started
     35 start_time = time.time()
     36 started_file_path = os.path.join(logdir, 'started')
     37 while not os.path.exists(started_file_path):
     38     time.sleep(1)
     39     if time.time() - start_time >= 30:
     40         raise Exception("autotestd failed to start in %s" % logdir)
     41 
     42 print >> stderr, 'Finished waiting on autotestd to start.'
     43 
     44 # watch the exit code file for an exit
     45 exit_code_file = open(os.path.join(logdir, 'exit_code'))
     46 fcntl.flock(exit_code_file, fcntl.LOCK_EX)
     47 print >> stderr, 'Got lock of exit_code_file.'
     48 try:
     49     exit_code = exit_code_file.read()
     50     if len(exit_code) != 4:
     51         exit_code = -signal.SIGKILL   # autotestd was nuked
     52     else:
     53         exit_code = int(exit_code)
     54 finally:
     55     fcntl.flock(exit_code_file, fcntl.LOCK_UN)
     56     exit_code_file.close()
     57     print >> stderr, 'Released lock of exit_code_file and closed it.'
     58 
     59 # tail runs in 1s polling loop, so give them a chance to finish
     60 time.sleep(2)
     61 
     62 print >> stderr, 'Killing child processes.'
     63 # clear the SIGCHLD handler so that killing the tails doesn't kill us
     64 signal.signal(signal.SIGCHLD, signal.SIG_DFL)
     65 os.kill(stdout_pump.pid, signal.SIGTERM)
     66 os.kill(stderr_pump.pid, signal.SIGTERM)
     67 
     68 # exit (with the same code as autotestd)
     69 sys.exit(exit_code)
     70