def receive(self, blocking=True): with Timeout.DisableAlarm(): if not blocking: return self.incoming.get(block=False) difference = Timeout.difference() if difference is not None: return self.incoming.get(timeout=difference) return self.incoming.get()
def test_check(self): with mocks.Time, OutputCapture() as capturer: with Timeout(1): Timeout.check() self.assertRaises(Timeout.Exception, time.sleep, 1) self.assertEqual( capturer.webkitcorepy.log.getvalue(), 'Request to sleep 1 second exceeded the current timeout threshold\n' )
def run(*popenargs, **kwargs): timeout = kwargs.pop('timeout', None) with Timeout.DisableAlarm(): current_time = time.time() Timeout.check(current_time=current_time) difference = Timeout.difference(current_time=current_time) if difference: timeout = min(timeout or sys.maxsize, int(math.ceil(difference))) return subprocess.run(*popenargs, timeout=timeout, **kwargs)
def test_nested_outer_timeout(self): with mocks.Time, OutputCapture() as capturer, self.assertRaises( Timeout.Exception): with Timeout(1): with Timeout(3, RuntimeError("This shouldn't be raised")): time.sleep(2) self.assertEqual( capturer.webkitcorepy.log.getvalue(), 'Request to sleep 2 seconds exceeded the current timeout threshold\n' )
def launch_app(self, bundle_id, args, env=None, timeout=300): environment_to_use = {} SIMCTL_ENV_PREFIX = 'SIMCTL_CHILD_' for value in (env or {}): if not value.startswith(SIMCTL_ENV_PREFIX): environment_to_use[SIMCTL_ENV_PREFIX + value] = env[value] else: environment_to_use[value] = env[value] # FIXME: This is a workaround for <rdar://problem/30172453>. def _log_debug_error(error): _log.debug(error.message_with_output()) with Timeout(timeout, handler=RuntimeError(u'Timed out waiting for process to open {} on {}'.format(bundle_id, self.udid)), patch=False): while True: output = self.executive.run_command( ['xcrun', 'simctl', 'launch', self.udid, bundle_id] + args, env=environment_to_use, error_handler=_log_debug_error, return_stderr=False, ) match = re.match(r'(?P<bundle>[^:]+): (?P<pid>\d+)\n', output) # FIXME: We shouldn't need to check the PID <rdar://problem/31154075>. if match and self.executive.check_running_pid(int(match.group('pid'))): break if match: _log.debug(u'simctl launch reported pid {}, but this process is not running'.format(match.group('pid'))) else: _log.debug('simctl launch did not report a pid') if match.group('bundle') != bundle_id: raise RuntimeError(u'Failed to find process id for {}: {}'.format(bundle_id, output)) _log.debug(u'Returning pid {} of launched process'.format(match.group('pid'))) return int(match.group('pid'))
def __exit__(self, *args, **kwargs): try: inflight = sys.exc_info() for worker in self.workers: if worker.is_alive(): worker.terminate() with Timeout(seconds=self.grace_period): try: while self._started: self.queue.receive()(self) except Exception: if inflight[1]: log.critical( 'Some workers failed to gracefully shut down, but in-flight exception taking precedence' ) reraise(*inflight) raise self.Exception( 'Some workers failed to gracefully shut down') finally: for worker in self.workers: if not worker.is_alive(): continue if sys.version_info >= (3, 7): worker.kill() elif hasattr(signal, 'SIGKILL'): os.kill(worker.pid, signal.SIGKILL) else: worker.terminate()
def _run_google_test(self, test_program, subtest): command = [test_program, '--gtest_filter=%s' % (subtest)] timeout = self._options.timeout if self._expectations.is_slow(os.path.basename(test_program), subtest): timeout *= 10 pid, fd = os.forkpty() if pid == 0: os.execvpe(command[0], command, self._test_env) sys.exit(0) with Timeout(timeout): try: common.parse_output_lines(fd, sys.stdout.write) status = self._waitpid(pid) os.close(fd) except Timeout.Exception: self._kill_process(pid) os.close(fd) sys.stdout.write("**TIMEOUT** %s\n" % subtest) sys.stdout.flush() return {subtest: "TIMEOUT"} if status == -SIGSEGV: sys.stdout.write("**CRASH** %s\n" % subtest) sys.stdout.flush() return {subtest: "CRASH"} if status != 0: return {subtest: "FAIL"} return {subtest: "PASS"}
def test_single_trigger(self): with mocks.Time, OutputCapture(): with Timeout(1): with self.assertRaises(Timeout.Exception): time.sleep(2) time.sleep( 2 ) # The timeout has already been triggered, so it shouldn't be re-triggered.
def run(*popenargs, **kwargs): timeout = kwargs.pop('timeout', None) capture_output = kwargs.pop('capture_output', False) with Timeout.DisableAlarm(): current_time = time.time() Timeout.check(current_time=current_time) difference = Timeout.difference(current_time=current_time) if difference: timeout = min(timeout or sys.maxsize, int(math.ceil(difference))) if capture_output: if ('stdout' in kwargs) or ('stderr' in kwargs): raise ValueError('stdout and stderr arguments may not be used with capture_output.') kwargs['stdout'] = subprocess.PIPE kwargs['stderr'] = subprocess.PIPE return subprocess.run(*popenargs, timeout=timeout, **kwargs)
def __enter__(self): with Timeout(seconds=10, patch=False, handler=self.Exception('Failed to start all workers')): for worker in self.workers: worker.start() while self._started < len(self.workers): self.queue.receive()(self) return self
def run(*popenargs, **kwargs): input = kwargs.pop('input', None) capture_output = kwargs.pop('capture_output', False) timeout = kwargs.pop('timeout', None) check = kwargs.pop('check', False) encoding = kwargs.pop('encoding', None) errors = kwargs.pop('errors', None) if encoding or errors: def decode(string): return string_utils.decode(string, encoding=encoding or 'utf-8', errors=errors or 'strict') else: def decode(string): return string if input is not None: if 'stdin' in kwargs: raise ValueError('stdin and input arguments may not both be used.') kwargs['stdin'] = subprocess.PIPE if capture_output: if ('stdout' in kwargs) or ('stderr' in kwargs): raise ValueError('stdout and stderr arguments may not be used with capture_output.') kwargs['stdout'] = subprocess.PIPE kwargs['stderr'] = subprocess.PIPE process = subprocess.Popen(*popenargs, **kwargs) try: if timeout: with Timeout(timeout): stdout, stderr = process.communicate(input) else: stdout, stderr = process.communicate(input) except Timeout.Exception: process.terminate() deadline = time.time() + .5 while process.poll() is None and time.time() < deadline: time.sleep(.1) if process.poll() is None: process.kill() stdout, stderr = '', '' else: stdout, stderr = process.communicate() raise TimeoutExpired(popenargs[0], timeout, output=decode(stdout), stderr=decode(stderr)) except BaseException: process.kill() raise finally: process.wait() retcode = process.poll() if check and retcode: raise subprocess.CalledProcessError(retcode, popenargs[0], output=decode(stdout), stderr=decode(stderr)) return CompletedProcess(popenargs[0], retcode, decode(stdout), decode(stderr))
def test_timeout_data(self): tmp = Timeout(1) self.assertEqual(None, tmp.data) with tmp: self.assertNotEqual(None, tmp.data) self.assertEqual(threading.current_thread().ident, tmp.data.thread_id) self.assertTrue(time.time() + 1 >= tmp.data.alarm_time) self.assertEqual(None, tmp.data)
def test_basic_timeout(self): with mocks.Time, OutputCapture() as capturer, self.assertRaises( Timeout.Exception): with Timeout(1): time.sleep(2) self.assertEqual( capturer.webkitcorepy.log.getvalue(), 'Request to sleep 2 seconds exceeded the current timeout threshold\n' )
def test_exception_constructor_timeout(self): with mocks.Time, OutputCapture() as capturer, self.assertRaises( RuntimeError): with Timeout(1, RuntimeError('This should be raised')): time.sleep(2) self.assertEqual( capturer.webkitcorepy.log.getvalue(), 'Request to sleep 2 seconds exceeded the current timeout threshold\n' )
def __exit__(self, *args, **kwargs): if not self.queue: TaskPool.Process.working = False try: if self._teardown_args[0]: self._teardown_args[0](*self._teardown_args[1], **self._teardown_args[2]) finally: TaskPool.Process.queue = None TaskPool.Process.name = None return from six import reraise try: inflight = sys.exc_info() for worker in self.workers: if worker.is_alive(): worker.terminate() with Timeout(seconds=self.grace_period): try: while self._started: self.queue.receive()(self) except Exception: if inflight[1]: log.critical( 'Some workers failed to gracefully shut down, but in-flight exception taking precedence' ) reraise(*inflight) raise self.Exception( 'Some workers failed to gracefully shut down') finally: for worker in self.workers: if not worker.is_alive(): continue if sys.version_info >= (3, 7): worker.kill() elif hasattr(signal, 'SIGKILL'): try: os.kill(worker.pid, signal.SIGKILL) except OSError as e: log.warn('Failed to terminate worker ' + str(worker.pid) + ' with error ' + str(e)) else: worker.terminate() self.queue.close() self.queue = None self.workers = []
def test_nested_outer_precedence(self): tmp_outer = Timeout(1) tmp_inner = Timeout(2) with tmp_outer: self.assertEqual(tmp_outer.data, Timeout.current()) with tmp_inner: self.assertEqual(tmp_outer.data, Timeout.current()) self.assertEqual(tmp_outer.data, Timeout.current()) self.assertEqual(None, Timeout.current())
def _start(self): if self._proc: raise ValueError('{} already running'.format(self._name)) self._reset() # Each device has a listening socket intitilaized during the port's setup_test_run. # 3 client connections will be accepted for stdin, stdout and stderr in that order. self._target_host.listening_socket.listen(3) self._pid = self._target_host.launch_app(self._bundle_id, self._cmd[1:], env=self._env) self._system_pid = self._pid # FIXME <rdar://problem/57032042>: This timeout should be 15 seconds with Timeout(30, handler=RuntimeError( 'Timed out waiting for pid {} to connect at port {}'. format(self._pid, self._target_host.listening_port())), patch=False): stdin = None stdout = None stderr = None try: # This order matches the client side connections in Tools/TestRunnerShared/IOSLayoutTestCommunication.cpp setUpIOSLayoutTestCommunication() stdin = SimulatorProcess._accept_connection_create_file( self._target_host.listening_socket, 'wb') stdout = SimulatorProcess._accept_connection_create_file( self._target_host.listening_socket, 'rb') stderr = SimulatorProcess._accept_connection_create_file( self._target_host.listening_socket, 'rb') except: # We set self._proc as _reset() and _kill() depend on it. self._proc = SimulatorProcess.Popen(self._pid, stdin, stdout, stderr, self._target_host) if self._proc.poll() is not None: self._reset() raise Exception( 'App {} with pid {} crashed before stdin could be attached' .format(os.path.basename(self._cmd[0]), self._pid)) self._kill() self._reset() raise self._proc = SimulatorProcess.Popen(self._pid, stdin, stdout, stderr, self._target_host)
def _run_one_test(self, web_root, test_file): try: self._http_server_driver.serve(web_root) url = urljoin(self._http_server_driver.base_url(), self._plan_name + '/' + test_file) self._browser_driver.launch_url(url, self._plan['options'], self._build_dir, self._browser_path) with Timeout(self._plan['timeout']): result = self._get_result(url) except Exception as error: self._browser_driver.diagnose_test_failure(self._diagnose_dir, error) raise error finally: self._browser_driver.close_browsers() self._http_server_driver.kill_server() return json.loads(result)
def __enter__(self): if not self.force_fork and self._num_workers == 1: TaskPool.Process.queue = _DummyQueue() TaskPool.Process.name = TaskPool.Process.name or '{}/0'.format( self.name) if self._setup_args[0]: self._setup_args[0](*self._setup_args[1], **self._setup_args[2]) TaskPool.Process.working = True return self from mock import patch self.queue = self.BiDirectionalQueue() self.workers = [ multiprocessing.Process( target=self.Process.main, args=( '{}/{}'.format(self.name, count), logging.getLogger().getEffectiveLevel(), self._setup_args[0], self._setup_args[1], self._setup_args[2], self.BiDirectionalQueue(outgoing=self.queue.incoming, incoming=self.queue.outgoing), self._teardown_args[0], self._teardown_args[1], self._teardown_args[2], ), ) for count in range(self._num_workers) ] with Timeout(seconds=10, patch=False, handler=self.Exception('Failed to start all workers')): for worker in self.workers: worker.start() while self._started < len(self.workers): self.queue.receive()(self) return self
def wait(self): if self.poll() is not None: return # Need to check the timeout context timeout = Timeout.difference() if timeout and (self._completion.elapsed is None or timeout < self._completion.elapsed): raise TimeoutExpired(self._args, timeout) if self._completion.elapsed is None: raise ValueError( 'Running a command that hangs without a timeout') if self._completion.elapsed: time.sleep(self._completion.elapsed) self.returncode = self._completion.returncode if self.stdout: self.stdout.seek(0) if self.stderr: self.stderr.seek(0)
def test_run_timeout_context(self): with OutputCapture(), self.assertRaises(TimeoutExpired): with Timeout(1): run([sys.executable, '-c', 'import time;time.sleep(2)'])
def test_no_timeout(self): with mocks.Time, OutputCapture() as capturer: with Timeout(2): time.sleep(1) self.assertEqual(capturer.webkitcorepy.log.getvalue(), '')
def test_deadline(self): with mocks.Time: with Timeout(1): self.asssertIsClose(Timeout.deadline(), time.time() + 1)
def test_difference(self): with mocks.Time: with Timeout(1): self.asssertIsClose(Timeout.difference(), 1)
def test_current_timeout(self): self.assertEqual(None, Timeout.current()) with Timeout(1) as tmp: self.assertEqual(tmp.data, Timeout.current()) self.assertEqual(None, Timeout.current())