예제 #1
0
    def post_fork_child(self):
        """Post-fork child process callback executed via ProcessManager.daemonize()."""
        # Set the Exiter exception hook post-fork so as not to affect the pantsd processes exception
        # hook with socket-specific behavior.
        self._exiter.set_except_hook()

        # Set context in the process title.
        set_process_title('pantsd-runner [{}]'.format(' '.join(self._args)))

        # Broadcast our pid to the remote client so they can send us signals (i.e. SIGINT).
        NailgunProtocol.write_chunk(self._socket, ChunkType.PID,
                                    bytes(os.getpid()))

        # Setup a SIGINT signal handler.
        self._setup_sigint_handler()

        # Invoke a Pants run with stdio redirected.
        with self._nailgunned_stdio(self._socket):
            try:
                # Clean global state.
                clean_global_runtime_state(reset_subsystem=True)

                # Re-raise any deferred exceptions, if present.
                self._raise_deferred_exc()

                # Otherwise, conduct a normal run.
                LocalPantsRunner(self._exiter, self._args, self._env,
                                 self._graph_helper).run()
            except KeyboardInterrupt:
                self._exiter.exit(1, msg='Interrupted by user.\n')
            except Exception:
                self._exiter.handle_unhandled_exception(add_newline=True)
            else:
                self._exiter.exit(0)
예제 #2
0
    def _run(self,
             is_remote,
             exiter,
             args,
             env,
             process_metadata_dir=None,
             options_bootstrapper=None):
        if is_remote:
            try:
                return RemotePantsRunner(exiter, args, env,
                                         process_metadata_dir).run()
            except RemotePantsRunner.RECOVERABLE_EXCEPTIONS as e:
                # N.B. RemotePantsRunner will raise one of RECOVERABLE_EXCEPTIONS in the event we
                # encounter a failure while discovering or initially connecting to the pailgun. In
                # this case, we fall back to LocalPantsRunner which seamlessly executes the requested
                # run and bootstraps pantsd for use in subsequent runs.
                logger.debug(
                    'caught client exception: {!r}, falling back to LocalPantsRunner'
                    .format(e))

        # N.B. Inlining this import speeds up the python thin client run by about 100ms.
        from pants.bin.local_pants_runner import LocalPantsRunner

        return LocalPantsRunner(
            exiter, args, env,
            options_bootstrapper=options_bootstrapper).run()
예제 #3
0
    def post_fork_child(self):
        """Post-fork child process callback executed via ProcessManager.daemonize()."""
        # Set the Exiter exception hook post-fork so as not to affect the pantsd processes exception
        # hook with socket-specific behavior. Note that this intentionally points the faulthandler
        # trace stream to sys.stderr, which at this point is still a _LoggerStream object writing to
        # the `pantsd.log`. This ensures that in the event of e.g. a hung but detached pantsd-runner
        # process that the stacktrace output lands deterministically in a known place vs to a stray
        # terminal window.
        self._exiter.set_except_hook(sys.stderr)

        # Ensure anything referencing sys.argv inherits the Pailgun'd args.
        sys.argv = self._args

        # Set context in the process title.
        set_process_title('pantsd-runner [{}]'.format(' '.join(self._args)))

        # Broadcast our process group ID (in PID form - i.e. negated) to the remote client so
        # they can send signals (e.g. SIGINT) to all processes in the runners process group.
        NailgunProtocol.send_pid(self._socket, bytes(os.getpgrp() * -1))

        # Setup a SIGINT signal handler.
        self._setup_sigint_handler()

        # Invoke a Pants run with stdio redirected and a proxied environment.
        with self._nailgunned_stdio(
                self._socket) as finalizer, hermetic_environment_as(
                    **self._env):
            try:
                # Setup the Exiter's finalizer.
                self._exiter.set_finalizer(finalizer)

                # Clean global state.
                clean_global_runtime_state(reset_subsystem=True)

                # Re-raise any deferred exceptions, if present.
                self._raise_deferred_exc()

                # Otherwise, conduct a normal run.
                runner = LocalPantsRunner(
                    self._exiter,
                    self._args,
                    self._env,
                    target_roots=self._target_roots,
                    daemon_build_graph=self._graph_helper)
                runner.set_start_time(
                    self._maybe_get_client_start_time_from_env(self._env))
                runner.set_preceding_graph_size(self._preceding_graph_size)
                runner.run()
            except KeyboardInterrupt:
                self._exiter.exit(1, msg='Interrupted by user.\n')
            except Exception:
                self._exiter.handle_unhandled_exception(add_newline=True)
            else:
                self._exiter.exit(0)
예제 #4
0
 def _run(self, is_remote, exiter, args, env, options_bootstrapper=None):
     if is_remote:
         try:
             return RemotePantsRunner(exiter, args, env).run()
         except RemotePantsRunner.RECOVERABLE_EXCEPTIONS as e:
             # N.B. RemotePantsRunner will raise one of RECOVERABLE_EXCEPTIONS in the event we
             # encounter a failure while discovering or initially connecting to the pailgun. In
             # this case, we fall back to LocalPantsRunner which seamlessly executes the requested
             # run and bootstraps pantsd for use in subsequent runs.
             logger.debug(
                 'caught client exception: {!r}, falling back to LocalPantsRunner'
                 .format(e))
     return LocalPantsRunner(
         exiter, args, env,
         options_bootstrapper=options_bootstrapper).run()
예제 #5
0
    def post_fork_child(self):
        """Post-fork child process callback executed via ProcessManager.daemonize()."""
        # Set the Exiter exception hook post-fork so as not to affect the pantsd processes exception
        # hook with socket-specific behavior. Note that this intentionally points the faulthandler
        # trace stream to sys.stderr, which at this point is still a _LoggerStream object writing to
        # the `pantsd.log`. This ensures that in the event of e.g. a hung but detached pantsd-runner
        # process that the stacktrace output lands deterministically in a known place vs to a stray
        # terminal window.
        self._exiter.set_except_hook(sys.stderr)

        # Ensure anything referencing sys.argv inherits the Pailgun'd args.
        sys.argv = self._args

        # Set context in the process title.
        set_process_title('pantsd-runner [{}]'.format(' '.join(self._args)))

        # Broadcast our pid to the remote client so they can send us signals (i.e. SIGINT).
        NailgunProtocol.write_chunk(self._socket, ChunkType.PID,
                                    bytes(os.getpid()))

        # Setup a SIGINT signal handler.
        self._setup_sigint_handler()

        # Invoke a Pants run with stdio redirected.
        with self._nailgunned_stdio(self._socket):
            try:
                # Clean global state.
                clean_global_runtime_state(reset_subsystem=True)

                # Re-raise any deferred exceptions, if present.
                self._raise_deferred_exc()

                # Otherwise, conduct a normal run.
                LocalPantsRunner(self._exiter, self._args, self._env,
                                 self._graph_helper).run()
            except KeyboardInterrupt:
                self._exiter.exit(1, msg='Interrupted by user.\n')
            except Exception:
                self._exiter.handle_unhandled_exception(add_newline=True)
            else:
                self._exiter.exit(0)
예제 #6
0
  def run(self):
    options_bootstrapper = OptionsBootstrapper(env=self._env, args=self._args)
    bootstrap_options = options_bootstrapper.get_bootstrap_options()

    if bootstrap_options.for_global_scope().enable_pantsd:
      try:
        return RemotePantsRunner(self._exiter, self._args, self._env, bootstrap_options).run()
      except RemotePantsRunner.Fallback as e:
        logger.warn('caught client exception: {!r}, falling back to non-daemon mode'.format(e))

    # N.B. Inlining this import speeds up the python thin client run by about 100ms.
    from pants.bin.local_pants_runner import LocalPantsRunner

    runner = LocalPantsRunner(
        self._exiter,
        self._args,
        self._env,
        options_bootstrapper=options_bootstrapper
    )
    runner.set_start_time(self._start_time)
    return runner.run()