Skip to content
Permalink
Browse files

fix _raise_deferred_exc() (pantsbuild#7008)

### Problem

The `_raise_deferred_exc(self)` method in `daemon_pants_runner.py` hasn't ever been tested. As a result, it causes an easily fixable error: the issue can be easily reproduced if you register an option twice in the same task and then run with pantsd enabled (you get the wrong exception, because `exc_type` isn't needed to construct the exception again, that's what `exc_value` is for).

### Solution

- Appropriately destructure `sys.exc_info()` (if that was what was used to populate `self._deferred_exception`) and re-raise the exception with its original traceback.

### Result

This error is fixed, but not yet tested -- see pantsbuild#7220.
  • Loading branch information...
cosmicexplorer committed Feb 6, 2019
1 parent f0a1a9f commit f28164226476d8092616285b9ea9208e2c29361b
Showing with 10 additions and 8 deletions.
  1. +10 −8 src/python/pants/bin/daemon_pants_runner.py
@@ -231,18 +231,16 @@ def nailgunned_stdio(cls, sock, env, handle_stdin=True):
) as finalizer:
yield finalizer

# TODO: there's no testing for this method, and this caused a user-visible failure -- see #7008!
def _raise_deferred_exc(self):
"""Raises deferred exceptions from the daemon's synchronous path in the post-fork client."""
if self._deferred_exception:
exc_type, exc_value, exc_traceback = self._deferred_exception
if exc_type == GracefulTerminationException:
self._exiter.exit(exc_value.exit_code)
try:
# Expect `_deferred_exception` to be a 3-item tuple of the values returned by sys.exc_info().
# This permits use the 3-arg form of the `raise` statement to preserve the original traceback.
raise_with_traceback(exc_type(exc_value), exc_traceback)
except ValueError:
# If `_deferred_exception` isn't a 3-item tuple, treat it like a bare exception.
exc_type, exc_value, exc_traceback = self._deferred_exception
raise_with_traceback(exc_value, exc_traceback)
except TypeError:
# If `_deferred_exception` isn't a 3-item tuple (raising a TypeError on the above
# destructuring), treat it like a bare exception.
raise self._deferred_exception

def _maybe_get_client_start_time_from_env(self, env):
@@ -327,6 +325,10 @@ def post_fork_child(self):
runner.run()
except KeyboardInterrupt:
self._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)
except Exception:
ExceptionSink._log_unhandled_exception_and_exit()
else:

0 comments on commit f281642

Please sign in to comment.
You can’t perform that action at this time.