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)
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()
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)
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()
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)
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()