1#! /usr/bin/env python 2# encoding: utf-8 3# Thomas Nagy, 2016-2018 (ita) 4 5import os, sys, traceback, base64, signal 6try: 7 import cPickle 8except ImportError: 9 import pickle as cPickle 10 11try: 12 import subprocess32 as subprocess 13except ImportError: 14 import subprocess 15 16try: 17 TimeoutExpired = subprocess.TimeoutExpired 18except AttributeError: 19 class TimeoutExpired(Exception): 20 pass 21 22def run(): 23 txt = sys.stdin.readline().strip() 24 if not txt: 25 # parent process probably ended 26 sys.exit(1) 27 [cmd, kwargs, cargs] = cPickle.loads(base64.b64decode(txt)) 28 cargs = cargs or {} 29 30 if not 'close_fds' in kwargs: 31 # workers have no fds 32 kwargs['close_fds'] = False 33 34 ret = 1 35 out, err, ex, trace = (None, None, None, None) 36 try: 37 proc = subprocess.Popen(cmd, **kwargs) 38 try: 39 out, err = proc.communicate(**cargs) 40 except TimeoutExpired: 41 if kwargs.get('start_new_session') and hasattr(os, 'killpg'): 42 os.killpg(proc.pid, signal.SIGKILL) 43 else: 44 proc.kill() 45 out, err = proc.communicate() 46 exc = TimeoutExpired(proc.args, timeout=cargs['timeout'], output=out) 47 exc.stderr = err 48 raise exc 49 ret = proc.returncode 50 except Exception as e: 51 exc_type, exc_value, tb = sys.exc_info() 52 exc_lines = traceback.format_exception(exc_type, exc_value, tb) 53 trace = str(cmd) + '\n' + ''.join(exc_lines) 54 ex = e.__class__.__name__ 55 56 # it is just text so maybe we do not need to pickle() 57 tmp = [ret, out, err, ex, trace] 58 obj = base64.b64encode(cPickle.dumps(tmp)) 59 sys.stdout.write(obj.decode()) 60 sys.stdout.write('\n') 61 sys.stdout.flush() 62 63while 1: 64 try: 65 run() 66 except KeyboardInterrupt: 67 break 68 69