def _await_nailgun_server(self, stdout, stderr, debug_desc): # TODO(Eric Ayers) Make these cmdline/config parameters once we have a global way to fetch # the global options scope. nailgun_timeout_seconds = 10 max_socket_connect_attempts = 5 nailgun = None port_parse_start = time.time() with safe_open(self._ng_out, 'r') as ng_out: while not nailgun: started = ng_out.readline() if started.find( 'Listening for transport dt_socket at address:') >= 0: nailgun_timeout_seconds = 60 logger.warn( 'Timeout extended to {timeout} seconds for debugger to attach to ng server.' .format(timeout=nailgun_timeout_seconds)) started = ng_out.readline() if started: port = self._parse_nailgun_port(started) nailgun = self._create_ngclient(port, stdout, stderr) logger.debug('Detected ng server up on port {port}'.format( port=port)) elif time.time() - port_parse_start > nailgun_timeout_seconds: raise NailgunClient.NailgunError( 'Failed to read ng output after {sec} seconds.\n {desc}' .format(sec=nailgun_timeout_seconds, desc=debug_desc)) attempt = 0 while nailgun: sock = nailgun.try_connect() if sock: sock.close() endpoint = self._get_nailgun_endpoint() if endpoint: logger.debug( 'Connected to ng server launched with {endpoint}'. format(endpoint=repr(endpoint))) else: raise NailgunClient.NailgunError( 'Failed to connect to ng server.') return nailgun elif attempt > max_socket_connect_attempts: raise nailgun.NailgunError( 'Failed to connect to ng output after {count} connect attempts' .format(count=max_socket_connect_attempts)) attempt += 1 logger.debug( 'Failed to connect on attempt {count}'.format(count=attempt)) time.sleep(0.1)
def _await_socket(self, timeout): """Blocks for the nailgun subprocess to bind and emit a listening port in the nailgun stdout.""" with safe_open(self._ng_stdout, 'r') as ng_stdout: start_time = time.time() accumulated_stdout = '' while 1: readable, _, _ = select.select([ng_stdout], [], [], self._SELECT_WAIT) if readable: line = ng_stdout.readline() # TODO: address deadlock risk here. try: return self._NG_PORT_REGEX.match(line).group(1) except AttributeError: pass accumulated_stdout += line if (time.time() - start_time) > timeout: stderr = read_file(self._ng_stderr) raise NailgunClient.NailgunError( 'Failed to read nailgun output after {sec} seconds!\n' 'Stdout:\n{stdout}\nStderr:\n{stderr}'.format( sec=timeout, stdout=accumulated_stdout, stderr=stderr, ) )
def _parse_nailgun_port(self, line): match = self._PARSE_NG_PORT.match(line) if not match: raise NailgunClient.NailgunError( 'Failed to determine spawned ng port from response' ' line: {line}'.format(line=line)) return int(match.group(1))
def _await_nailgun_server(self, stdout, stderr): nailgun_timeout_seconds = 5 max_socket_connect_attempts = 10 nailgun = None port_parse_start = time.time() with safe_open(self._ng_out, 'r') as ng_out: while not nailgun: started = ng_out.readline() if started.find( 'Listening for transport dt_socket at address:') >= 0: nailgun_timeout_seconds = 60 log.warn( 'Timeout extended to {timeout} seconds for debugger to attach to ng server.' .format(timeout=nailgun_timeout_seconds)) started = ng_out.readline() if started: port = self._parse_nailgun_port(started) nailgun = self._create_ngclient(port, stdout, stderr) log.debug('Detected ng server up on port %d' % port) elif time.time() - port_parse_start > nailgun_timeout_seconds: raise NailgunClient.NailgunError( 'Failed to read ng output after' ' %s seconds' % nailgun_timeout_seconds) attempt = 0 while nailgun: sock = nailgun.try_connect() if sock: sock.close() endpoint = self._get_nailgun_endpoint() if endpoint: log.debug( 'Connected to ng server launched with %s fingerprint %s pid: %d @ port: %d' % endpoint) else: raise NailgunClient.NailgunError( 'Failed to connect to ng server.') return nailgun elif attempt > max_socket_connect_attempts: raise nailgun.NailgunError( 'Failed to connect to ng output after %d connect attempts' % max_socket_connect_attempts) attempt += 1 log.debug('Failed to connect on attempt %d' % attempt) time.sleep(0.1)
def ensure_connectable(self, nailgun): """Ensures that a nailgun client is connectable or raises NailgunError.""" attempt_count = 0 while 1: if attempt_count > self._connect_attempts: logger.debug('Failed to connect to ng after {count} attempts' .format(count=self._connect_attempts)) raise NailgunClient.NailgunError('Failed to connect to ng server.') try: sock = nailgun.try_connect() if sock: logger.debug('Connected to ng server {server!r}'.format(server=self)) return finally: sock.close() attempt_count += 1 time.sleep(self.WAIT_INTERVAL)