def ulimit(command, mem_limit=None, time_limit=None, **kwargs): # This could be nicely replaced with preexec_fn + resource.setrlimit, but # it does not work: RLIMIT_VMEM is usually not available (and we must take # into consideration that python has to fit in it before execve) command = isinstance(command, list) and command or [command] if mem_limit: command = ['ulimit', '-v', str(mem_limit), noquote('&&')] + command # Unlimited stack command = ['ulimit', '-Ss', 'unlimited', noquote('&&')] + command if time_limit: command = ['ulimit', '-t', str(ceil_ms2s(time_limit)), noquote('&&')] + command return command
def _execute(self, command, **kwargs): env = kwargs.get('env') env.update({ 'MEM_LIMIT': kwargs['mem_limit'] or 64 * 2**10, 'TIME_LIMIT': kwargs['time_limit'] or 30000, 'OUT_LIMIT': kwargs['output_limit'] or 50 * 2**20, }) if kwargs['real_time_limit']: env['HARD_LIMIT'] = 1 + ceil_ms2s(kwargs['real_time_limit']) elif kwargs['time_limit'] and kwargs['real_time_limit'] is None: env['HARD_LIMIT'] = 1 + ceil_ms2s(64 * kwargs['time_limit']) if 'HARD_LIMIT' in env: # Limiting outside supervisor kwargs['real_time_limit'] = 2 * s2ms(env['HARD_LIMIT']) ignore_errors = kwargs.pop('ignore_errors') extra_ignore_errors = kwargs.pop('extra_ignore_errors') renv = {} try: result_file = tempfile.NamedTemporaryFile(dir=tempcwd()) kwargs['ignore_errors'] = True renv = execute_command(command + [noquote('3>'), result_file.name], **kwargs) if 'real_time_killed' in renv: raise ExecError('Supervisor exceeded realtime limit') elif renv['return_code'] and renv[ 'return_code'] not in extra_ignore_errors: raise ExecError('Supervisor returned code %s' % renv['return_code']) result_file.seek(0) status_line = result_file.readline().strip().split()[1:] renv['result_string'] = result_file.readline().strip() result_file.close() for num, key in enumerate(('result_code', 'time_used', None, 'mem_used', 'num_syscalls')): if key: renv[key] = int(status_line[num]) result_code = self._supervisor_result_to_code(renv['result_code']) except Exception as e: logger.error('SupervisedExecutor error: %s', traceback.format_exc()) logger.error( 'SupervisedExecutor error dirlist: %s: %s', tempcwd(), str(os.listdir(tempcwd())), ) result_code = 'SE' for i in ('time_used', 'mem_used', 'num_syscalls'): renv.setdefault(i, 0) renv['result_string'] = str(e) renv['result_code'] = result_code if (result_code != 'OK' and not ignore_errors and not (result_code != 'RV' and renv['return_code'] in extra_ignore_errors)): raise ExecError('Failed to execute command: %s. Reason: %s' % (command, renv['result_string'])) return renv