import os
import subprocess
import tempfile
import time
from bugzscout import report_exception, report_error
MAX_RUN_TIME = 30 * 60 # 30 Minutes
BACKEND_AREA = 'Backend'
def start_proc(*args, **kwargs):
try:
outfile = tempfile.TemporaryFile()
errfile = tempfile.TemporaryFile()
proc = subprocess.Popen(args, stdout=outfile, stderr=errfile)
proc.args = args
proc.timeout = time.time() + kwargs.get('timeout', MAX_RUN_TIME)
proc.outfile = outfile
proc.errfile = errfile
return proc
except Exception, e:
extra = "Failed to start '%s'\n" % ' '.join(args)
report_exception(e, extra, area=kwargs.get('bugzscout_area', BACKEND_AREA))
def monitor_proc(proc, **kwargs):
retval = True
if not proc:
# We can't monitor nothing. Something probably failed in process creation.
return False
ret_code = None
while ret_code is None:
ret_code = proc.poll()
time.sleep(0.50)
if time.time() > proc.timeout:
# Time's up. Now you die.
ret_code = kill_proc(proc)
break
if ret_code:
# Something went wrong. Log it and put the repos back in the queue.
args = ' '.join(proc.args)
proc.outfile.seek(0)
proc.errfile.seek(0)
out = proc.outfile.read()
err = proc.errfile.read()
extra = '\n'.join([
'Command exited with code %s' % proc.returncode,
args,
'================StdErr==================',
err,
'================StdOut==================',
out,
])
report_error('Error running %s' % proc.args[0], extra, area=kwargs.get('bugzscout_area', BACKEND_AREA))
retval = False
proc.outfile.close()
proc.errfile.close()
return retval
def kill_proc(proc):
if os.name == 'posix':
# POSIX: os.kill sends signals.
from signal import SIGTERM, SIGKILL
os.kill(proc.pid, SIGTERM)
time.sleep(30) # You have 30 seconds to die
ret_code = proc.poll()
if not ret_code:
# Not dead yet...kill it again.
os.kill(proc.pid, SIGKILL)
ret_code = proc.poll() or -1
return ret_code
else:
# Windows: We have to use TerminateProcess
win_kill_tree(proc.pid)
time.sleep(30)
return proc.poll() or -1
def win_get_children(pid):
import win32com.client
wmi = win32com.client.GetObject('winmgmts:')
children = wmi.ExecQuery('SELECT * FROM win32_process WHERE ParentProcessId=%s' % pid)
pids = []
for proc in children:
pids.append(proc.Properties_('ProcessId'))
return pids
def win_kill_pid(pid):
import win32api
import win32con
import win32process
handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid)
win32process.TerminateProcess(handle, 1)
def win_kill_tree(pid):
children = win_get_children(pid)
win_kill_pid(pid)
for child in children:
win_kill_tree(child)
time.sleep(0.1)
|
Loading...