Beispiel #1
0
    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()
Beispiel #2
0
 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())
Beispiel #3
0
    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)
Beispiel #4
0
  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()