def _process_starter(timeout, args): """ Function just executes native scheduler client and waits until it terminates. :param timeout: Check that tool will exit definetly within this period of time. :param args: Native scheduler client execution command arguments. :return: It exits with the exit code returned by a client. """ # todo: implement proper self.logger here, since usage of self.logger lead to hanging of threads dont know why ####### !!!! ####### # I know that this is redundant code but you will not able to run clients code directly without this one!!!! # This is because bug in self.logger library. After an attempt to start the client with self.logger in a # separate process and then kill it and start it again self.logger will HANG and you WILL NOT able to start the # client again. This is known bug in self.logger, so do not waste your time here until it is fixed. ####### !!!! ####### # Kill handler mypid = os.getpid() with open('info.log', 'a') as lf: print('Executor {!r}: execute: {!r}'.format(mypid, ' '.join(args)), file=lf) ec = utils.execute(args, timeout=timeout) with open('info.log', 'a') as lf: print('Executor {!r}: Finished command: {!r}'.format( mypid, ' '.join(args)), file=lf) # Be sure that process will exit if not isinstance(ec, int): ec = 1 os._exit(int(ec))
def run(selflogger, args, conf, logger=None): """ Run given command with or without disk space limitations. :param selflogger: Logger to print log of this function. :param args: Command arguments. :param conf: Configuration dictionary of the client. :param logger: Logger object to print log of BenchExec or RunExec. :return: Exit code. """ if conf["resource limits"]["disk memory size"] and not \ (("runexec measure disk" in conf['client'] and conf['client']["runexec measure disk"]) or ("benchexec measure disk" in conf['client'] and conf['client']["benchexec measure disk"])): dl = conf["resource limits"]["disk memory size"] if "disk checking period" not in conf['client']: dcp = 60 else: dcp = conf['client']['disk checking period'] else: dcp = None dl = None if logger: ec = execute(args, logger=logger, disk_limitation=dl, disk_checking_period=dcp) if ec != 0: selflogger.info( "Executor exited with non-zero exit code {}".format(ec)) return ec else: with open('client-log.log', 'a', encoding="utf8") as ste, \ open('runexec stdout.log', 'w', encoding="utf8") as sto: ec = execute(args, logger=logger, disk_limitation=dl, disk_checking_period=dcp, stderr=ste, stdout=sto) # Runexec prints its warnings and ordinary log to STDERR, thus lets try to find warnings there and move them # to critical log file if os.path.isfile('client-log.log'): with open('client-log.log', encoding="utf8") as log: for line in log.readlines(): # Warnings can be added to the file only from RunExec if re.search(r'WARNING - (.*)', line): selflogger.warning(line.strip()) elif re.search(r'runexec: error: .*', line): selflogger.error(line.strip()) job_exit = None if ec == 0 and os.path.isfile('runexec stdout.log'): reason = None selflogger.info( "Get return code of the job since runexec successfully exited") with open('runexec stdout.log', 'r', encoding="utf8") as fp: for line in fp.readlines(): key, value = line.split('=') if key and value and key == 'exitcode': job_exit = int(value) if job_exit > 255: # Be cool as Unix is job_exit = job_exit >> 8 elif key and value and key == 'terminationreason': reason = str(value).rstrip() if reason: selflogger.warning( "RunExec set termination reason {!r}".format(reason)) if not os.path.isfile('runexec stdout.log') or job_exit is None: selflogger.info( "Runexec exited successfully but it is not possible to read job exit code, aborting" ) ec = 1 else: ec = job_exit return ec