def start(self): """Starts the runtime process and waits until it is ready to serve.""" runtime_config = self._runtime_config_getter() # TODO: Use a different process group to isolate the child process # from signals sent to the parent. Only available in subprocess in # Python 2.7. assert self._start_process_flavor in self._VALID_START_PROCESS_FLAVORS if self._start_process_flavor == START_PROCESS: serialized_config = base64.b64encode( runtime_config.SerializeToString()) with self._process_lock: assert not self._process, 'start() can only be called once' self._process = safe_subprocess.start_process( self._args, serialized_config, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=self._env, cwd=self._module_configuration.application_root) line = self._process.stdout.readline() elif self._start_process_flavor == START_PROCESS_FILE: serialized_config = runtime_config.SerializeToString() with self._process_lock: assert not self._process, 'start() can only be called once' self._process = safe_subprocess.start_process_file( args=self._args, input_string=serialized_config, env=self._env, cwd=self._module_configuration.application_root, stderr=subprocess.PIPE) line = self._read_start_process_file() _remove_retry_sharing_violation(self._process.child_out.name) # _stderr_tee may be pre-set by unit tests. if self._stderr_tee is None: self._stderr_tee = tee.Tee(self._process.stderr, sys.stderr) self._stderr_tee.start() port = None error = None try: port = int(line) except ValueError: error = 'bad runtime process port [%r]' % line logging.error(error) finally: self._proxy = http_proxy.HttpProxy( host='localhost', port=port, instance_died_unexpectedly=self._instance_died_unexpectedly, instance_logs_getter=self._get_instance_logs, error_handler_file=application_configuration. get_app_error_file(self._module_configuration), prior_error=error) self._proxy.wait_for_connection()
def test_tee(self): output = io.StringIO() tee.Tee._MAX_LINES = 3 t = tee.Tee(Counter(100), output) t.start() t.join() self.assertEqual('line98\nline99\nline100\n', t.get_buf()) expected = '' for i in range(100): expected += 'line%d\n' % (i + 1) self.assertEqual(expected, output.getvalue())
def start(self): """Starts the runtime process and waits until it is ready to serve.""" runtime_config = self._runtime_config_getter() # TODO: Use a different process group to isolate the child process # from signals sent to the parent. Only available in subprocess in # Python 2.7. assert self._start_process_flavor in self._VALID_START_PROCESS_FLAVORS if self._start_process_flavor == START_PROCESS: serialized_config = base64.b64encode( runtime_config.SerializeToString()) with self._process_lock: assert not self._process, 'start() can only be called once' self._process = safe_subprocess.start_process( self._args, serialized_config, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=self._env, cwd=self._module_configuration.application_root) line = self._process.stdout.readline() elif self._start_process_flavor == START_PROCESS_FILE: serialized_config = runtime_config.SerializeToString() with self._process_lock: assert not self._process, 'start() can only be called once' self._process = safe_subprocess.start_process_file( args=self._args, input_string=serialized_config, env=self._env, cwd=self._module_configuration.application_root, stderr=subprocess.PIPE) line = self._read_start_process_file() _remove_retry_sharing_violation(self._process.child_out.name) # _stderr_tee may be pre-set by unit tests. if self._stderr_tee is None: self._stderr_tee = tee.Tee(self._process.stderr, sys.stderr) self._stderr_tee.start() self._prior_error = None self._port = None try: # Older runtimes output just the port, while newer ones prepend the host. self._port = int(line.split()[-1]) except ValueError: self._prior_error = 'bad runtime process port [%r]' % line logging.error(self._prior_error) else: # Check if the runtime can serve requests. if not self._can_connect(): self._prior_error = 'cannot connect to runtime on port %r' % self._port logging.error(self._prior_error)
def start(self): """Starts the runtime process and waits until it is ready to serve.""" runtime_config = self._runtime_config_getter() # TODO: Use a different process group to isolate the child process # from signals sent to the parent. Only available in subprocess in # Python 2.7. assert self._start_process_flavor in self._VALID_START_PROCESS_FLAVORS host = 'localhost' if self._start_process_flavor == START_PROCESS: serialized_config = base64.b64encode(runtime_config.SerializeToString()) with self._process_lock: assert not self._process, 'start() can only be called once' self._process = safe_subprocess.start_process( self._args, serialized_config, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=self._env, cwd=self._module_configuration.application_root) port = self._process.stdout.readline() if '\t' in port: # Split out the host if present. host, port = port.split('\t', 1) elif self._start_process_flavor == START_PROCESS_FILE: serialized_config = runtime_config.SerializeToString() with self._process_lock: assert not self._process, 'start() can only be called once' self._process = safe_subprocess.start_process_file( args=self._args, input_string=serialized_config, env=self._env, cwd=self._module_configuration.application_root, stderr=subprocess.PIPE) port = self._read_start_process_file() _remove_retry_sharing_violation(self._process.child_out.name) elif self._start_process_flavor == START_PROCESS_REVERSE: serialized_config = runtime_config.SerializeToString() with self._process_lock: assert not self._process, 'start() can only be called once' port = portpicker.PickUnusedPort() self._env['PORT'] = str(port) # If any of the strings in args contain {port}, replace that substring # with the selected port. This allows a user-specified runtime to # pass the port along to the subprocess as a command-line argument. args = [arg.replace('{port}', str(port)) for arg in self._args] self._process = safe_subprocess.start_process_file( args=args, input_string=serialized_config, env=self._env, cwd=self._module_configuration.application_root, stderr=subprocess.PIPE) elif self._start_process_flavor == START_PROCESS_REVERSE_NO_FILE: serialized_config = runtime_config.SerializeToString() with self._process_lock: assert not self._process, 'start() can only be called once' port = portpicker.PickUnusedPort() if self._extra_args_getter: self._args.append(self._extra_args_getter(port)) # If any of the strings in _args contain {port}, {api_host}, {api_port}, # replace that substring with the selected port. This allows # a user-specified runtime to pass the port along to the subprocess # as a command-line argument. args = [arg.replace('{port}', str(port)) .replace('{api_port}', str(runtime_config.api_port)) .replace('{api_host}', runtime_config.api_host) for arg in self._args] self._process = safe_subprocess.start_process( args=args, input_string=serialized_config, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=self._env, cwd=self._module_configuration.application_root) # _stderr_tee may be pre-set by unit tests. if self._stderr_tee is None: self._stderr_tee = tee.Tee(self._process.stderr, sys.stderr) self._stderr_tee.start() error = None try: port = int(port) except ValueError: error = 'bad runtime process port [%r]' % port logging.error(error) finally: self._proxy = http_proxy.HttpProxy( host=host, port=port, instance_died_unexpectedly=self._instance_died_unexpectedly, instance_logs_getter=self._get_instance_logs, error_handler_file=application_configuration.get_app_error_file( self._module_configuration), prior_error=error) self._proxy.wait_for_connection()