#!/usr/bin/python
#
#  copyright (C) 2008  troy d. straszheim  <troy@resophonic.com>
#  
#  Distributed under the Boost Software License, Version 1.0.
#  See accompanying file LICENSE_1_0.txt or copy at
#  http://www.boost.org/LICENSE_1_0.txt
#
#
#  Compiler driver.  Takes a few arguments describing what is to be done
#  (used to mark up the output) and executes compiler in a subshell, checking
#  for errors and marshalling output to disk.
#
import sys, signal, threading, subprocess
sys.path.append("@BOOST_BUILD_SLAVE_PYTHONPATH@")
from boost_build_slave import *

import datetime, time, signal
from subprocess import Popen, PIPE
from kill_subprocess import kill_subprocess
from classify import classify

log = os.path.join(sys.argv[1], "Log.marshal")
op = sys.argv[2]
target = sys.argv[3]
argv = sys.argv[4:]
expect_fail = op.endswith("fail")

if os.name == 'nt':
    os.environ['PATH'] = r'@CMAKE_LIBRARY_OUTPUT_DIRECTORY@;' + os.environ['PATH']

print "***\n*** Executing op:" + op + "\n*** " + str(argv) + "\n*** log=" + log + "\n***"
#
#  execute subprocess, watch for timeout
#
class SubprocThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.ex = None

    def run(self):
        try:
            self.proc = Popen(argv, stdout=PIPE, stderr=PIPE)
            (self.stdout, self.stderr) = self.proc.communicate()
        except EnvironmentError, e:
            self.ex = e

t = SubprocThread()
starttime = datetime.datetime.now()
t.start()
t.join(timeout_seconds)

if t.isAlive():
    print "*** Killing subprocess after timeout"
    kill_subprocess(t.proc.pid)
    e = OSError()
    e.errno = 666
    e.message = e.strerror = "TIMEOUT AFTER %d SECONDS" % timeout_seconds
    e.filename = argv[0]
    t.ex = e

duration = datetime.datetime.now() - starttime

#
#  Collect and store subprocess info
#
result = { 'expect_fail' : expect_fail,
           'wallclock_duration' : duration.seconds + duration.microseconds * 10**-6 }

if not t.ex:
    result['returncode'] = t.proc.returncode
    result['stdout'] = t.stdout
    result['stderr'] = t.stderr

    if t.proc.returncode != 0 and not expect_fail:
        print "*** returncode: %d" % t.proc.returncode
        print "*** stdout:" + result['stdout']
        print "*** stderr:" + result['stderr']
else:
    result['errno'] = t.ex.errno
    result['filename'] = t.ex.filename
    result['message'] = t.ex.message
    result['strerror'] = t.ex.strerror
    print "Errno:" + str(t.ex.errno) + ": " + t.ex.strerror

result.update({'op' : op,
               'target' : target,
               'cmdline' : argv })

classify(result)
print "post classification: result=", result

f = open(log, "ab", 0)
marshal.dump(result, f)
f.close()

if t.ex:
    sys.exit(t.ex.errno)
else:
    if expect_fail:
        if t.proc.returncode != 0:
            sys.exit(0)
        else: 
            print "UNEXPECTED SUCCESS"
            sys.exit(1)  # we need an exit status for 'unexpected success'
    else:
        sys.exit(t.proc.returncode)

    

