-
-
Notifications
You must be signed in to change notification settings - Fork 652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wip - add contextmanager'd exiters and change return type of run() #7606
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -273,10 +273,6 @@ def _raise_deferred_exc(self): | |
# destructuring), treat it like a bare exception. | ||
raise self._deferred_exception | ||
|
||
def _maybe_get_client_start_time_from_env(self, env): | ||
client_start_time = env.pop('PANTSD_RUNTRACKER_CLIENT_START_TIME', None) | ||
return None if client_start_time is None else float(client_start_time) | ||
|
||
def run(self): | ||
"""Fork, daemonize and invoke self.post_fork_child() (via ProcessManager). | ||
|
||
|
@@ -332,40 +328,40 @@ def post_fork_child(self): | |
|
||
# Invoke a Pants run with stdio redirected and a proxied environment. | ||
with self.nailgunned_stdio(self._socket, self._env) as finalizer,\ | ||
hermetic_environment_as(**self._env): | ||
hermetic_environment_as(**self._env),\ | ||
ExceptionSink.exiter_as(self._exiter) as daemon_exiter: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we could avoid having |
||
try: | ||
# Setup the Exiter's finalizer. | ||
self._exiter.set_finalizer(finalizer) | ||
daemon_exiter.set_finalizer(finalizer) | ||
|
||
# Clean global state. | ||
clean_global_runtime_state(reset_subsystem=True) | ||
|
||
# Otherwise, conduct a normal run. | ||
runner = LocalPantsRunner.create( | ||
self._exiter, | ||
daemon_exiter, | ||
self._args, | ||
self._env, | ||
self._target_roots, | ||
self._graph_helper, | ||
self._options_bootstrapper | ||
) | ||
runner.set_start_time(self._maybe_get_client_start_time_from_env(self._env)) | ||
|
||
# Re-raise any deferred exceptions, if present. | ||
self._raise_deferred_exc() | ||
|
||
runner.run() | ||
exit_code = runner.run() | ||
daemon_exiter.exit(exit_code) | ||
except KeyboardInterrupt: | ||
self._exiter.exit_and_fail('Interrupted by user.\n') | ||
daemon_exiter.exit_and_fail('Interrupted by user.\n') | ||
except _GracefulTerminationException as e: | ||
ExceptionSink.log_exception( | ||
'Encountered graceful termination exception {}; exiting'.format(e)) | ||
self._exiter.exit(e.exit_code) | ||
daemon_exiter.exit(e.exit_code) | ||
except Exception: | ||
# TODO: We override sys.excepthook above when we call ExceptionSink.set_exiter(). That | ||
# excepthook catches `SignalHandledNonLocalExit`s from signal handlers, which isn't | ||
# happening here, so something is probably overriding the excepthook. By catching Exception | ||
# and calling this method, we emulate the normal, expected sys.excepthook override. | ||
ExceptionSink._log_unhandled_exception_and_exit() | ||
else: | ||
self._exiter.exit(PANTS_SUCCEEDED_EXIT_CODE) | ||
daemon_exiter.exit(PANTS_SUCCEEDED_EXIT_CODE) |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -5,6 +5,7 @@ | |||||
from __future__ import absolute_import, division, print_function, unicode_literals | ||||||
|
||||||
import logging | ||||||
import time | ||||||
from builtins import object, str | ||||||
|
||||||
from pants.base.build_environment import get_buildroot | ||||||
|
@@ -213,7 +214,7 @@ def __init__(self, build_root, exiter, options, options_bootstrapper, build_conf | |||||
self._repro = None | ||||||
self._global_options = options.for_global_scope() | ||||||
|
||||||
def set_start_time(self, start_time): | ||||||
def _set_start_time(self, start_time): | ||||||
# Launch RunTracker as early as possible (before .run() is called). | ||||||
self._run_tracker = RunTracker.global_instance() | ||||||
self._reporting = Reporting.global_instance() | ||||||
|
@@ -226,13 +227,9 @@ def set_start_time(self, start_time): | |||||
if self._repro: | ||||||
self._repro.capture(self._run_tracker.run_info.get_as_dict()) | ||||||
|
||||||
# The __call__ method of the Exiter allows for the prototype pattern. | ||||||
self._exiter = LocalExiter(self._run_tracker, self._repro, exiter=self._exiter) | ||||||
ExceptionSink.reset_exiter(self._exiter) | ||||||
|
||||||
def run(self): | ||||||
with maybe_profiled(self._profile_path): | ||||||
self._run() | ||||||
return self._run() | ||||||
|
||||||
def _maybe_handle_help(self): | ||||||
"""Handle requests for `help` information.""" | ||||||
|
@@ -286,22 +283,27 @@ def _compute_final_exit_code(*codes): | |||||
return max_code | ||||||
|
||||||
def _run(self): | ||||||
try: | ||||||
self._maybe_handle_help() | ||||||
self._set_start_time(time.time()) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not allowing the start time to be injected via environment variable anymore sounds like something we would want to note in the PR description perhaps. |
||||||
|
||||||
engine_result = self._maybe_run_v2() | ||||||
goal_runner_result = self._maybe_run_v1() | ||||||
finally: | ||||||
# wrap the outer exiter | ||||||
local_exiter = LocalExiter(self._run_tracker, self._repro, exiter=self._exiter) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
with ExceptionSink.exiter_as(local_exiter): | ||||||
try: | ||||||
run_tracker_result = self._run_tracker.end() | ||||||
except ValueError as e: | ||||||
# Calling .end() sometimes writes to a closed file, so we return a dummy result here. | ||||||
logger.exception(e) | ||||||
run_tracker_result = PANTS_SUCCEEDED_EXIT_CODE | ||||||
|
||||||
final_exit_code = self._compute_final_exit_code( | ||||||
engine_result, | ||||||
goal_runner_result, | ||||||
run_tracker_result | ||||||
) | ||||||
self._exiter.exit(final_exit_code) | ||||||
self._maybe_handle_help() | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this will |
||||||
|
||||||
engine_result = self._maybe_run_v2() | ||||||
goal_runner_result = self._maybe_run_v1() | ||||||
finally: | ||||||
try: | ||||||
run_tracker_result = self._run_tracker.end() | ||||||
except ValueError as e: | ||||||
# Calling .end() sometimes writes to a closed file, so we return a dummy result here. | ||||||
logger.exception(e) | ||||||
run_tracker_result = PANTS_SUCCEEDED_EXIT_CODE | ||||||
|
||||||
final_exit_code = self._compute_final_exit_code( | ||||||
engine_result, | ||||||
goal_runner_result, | ||||||
run_tracker_result | ||||||
) | ||||||
return final_exit_code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is needed, as
ExceptionSink.reset_exiter()
already overrides the class variables :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need to edit
reset_exiter()
the way we didreset_signal_handler()
in order to supporttrapped_signals()
in #6574. Luckily all that would mean is makingreset_exiter()
return the previous exiter.pants/src/python/pants/base/exception_sink.py
Lines 278 to 311 in f9b0313