# Buggy code
def reset_log_location(cls, new_log_location):
    """Re-acquire file handles to error logs based in the new location.

    Class state:
    - Overwrites `cls._log_dir`, `cls._pid_specific_error_fileobj`, and
      `cls._shared_error_fileobj`.
    OS state:
    - May create a new directory.
    - Overwrites signal handlers for many fatal and non-fatal signals.

    :raises: :class:`ExceptionSink.ExceptionSinkError` if the directory does not exist or is not
             writable.
    """
    # We could no-op here if the log locations are the same, but there's no reason not to have the
    # additional safety of re-acquiring file descriptors each time (and erroring out early if the
    # location is no longer writable).

    # Create the directory if possible, or raise if not writable.
    cls._check_or_create_new_destination(new_log_location)

    pid_specific_error_stream, shared_error_stream = (
        cls._recapture_fatal_error_log_streams(new_log_location)
    )

    # NB: mutate process-global state!
    if faulthandler.is_enabled():
        logger.debug("re-enabling faulthandler")
        # Call Py_CLEAR() on the previous error stream:
        # https://github.com/vstinner/faulthandler/blob/master/faulthandler.c
        faulthandler.disable()
    # Send a stacktrace to this file if interrupted by a fatal error.
    faulthandler.enable(file=pid_specific_error_stream, all_threads=True)
    # Log a timestamped exception and exit gracefully on non-fatal signals.
    for signum in cls.all_gracefully_handled_signals:
        signal.signal(signum, cls.handle_signal_gracefully)
        signal.siginterrupt(signum, False)

    # NB: mutate the class variables!
    cls._log_dir = new_log_location
    cls._pid_specific_error_fileobj = pid_specific_error_stream
    cls._shared_error_fileobj = shared_error_stream


# Traceback (AssertionError)
23:26:42 01:10       [run]
============== test session starts ===============
platform darwin -- Python 2.7.10, pytest-3.6.4, py-1.7.0, pluggy-0.7.1 -- /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
cachedir: .pants.d/.pytest_cache
rootdir: /Users/travis/build/pantsbuild/pants/.pants.d, inifile: /Users/travis/build/pantsbuild/pants/.pants.d/test/pytest-prep/CPython-2.7.10/e241a5f8b7de6d34689cc9307d8d06eb155c7c78/pytest.ini
plugins: timeout-1.2.1, cov-2.4.0
collecting ... collected 7 items

tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_dumps_logs_on_terminate <- ../../../../../../System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py SKIPPED [ 14%]
tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_dumps_traceback_on_sigabrt <- pyprep/sources/4d9f3a72ced4c3b5cabbfead9552e9e3e78a30ca/pants_test/base/test_exception_sink_integration.py PASSED [ 28%]
tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_keyboardinterrupt_signals <- pyprep/sources/4d9f3a72ced4c3b5cabbfead9552e9e3e78a30ca/pants_test/base/test_exception_sink_integration.py FAILED [ 42%]
tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_logs_unhandled_exception <- pyprep/sources/4d9f3a72ced4c3b5cabbfead9552e9e3e78a30ca/pants_test/base/test_exception_sink_integration.py PASSED [ 57%]
tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_prints_traceback_on_sigusr2 <- pyprep/sources/4d9f3a72ced4c3b5cabbfead9552e9e3e78a30ca/pants_test/base/test_exception_sink_integration.py PASSED [ 71%]
tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_reset_exiter <- pyprep/sources/4d9f3a72ced4c3b5cabbfead9552e9e3e78a30ca/pants_test/base/test_exception_sink_integration.py PASSED [ 85%]
tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_reset_interactive_output_stream <- pyprep/sources/4d9f3a72ced4c3b5cabbfead9552e9e3e78a30ca/pants_test/base/test_exception_sink_integration.py PASSED [100%]

==================== FAILURES ====================
ExceptionSinkIntegrationTest.test_keyboardinterrupt_signals

self = <pants_test.base.test_exception_sink_integration.ExceptionSinkIntegrationTest testMethod=test_keyboardinterrupt_signals>

def test_keyboardinterrupt_signals(self):
for interrupt_signal in [signal.SIGINT, signal.SIGQUIT]:
with self._send_signal_to_waiter_handle(interrupt_signal) as (workdir, waiter_run):
>         self.assertIn('Interrupted by user.\n', waiter_run.stderr_data)
E         AssertionError: u'Interrupted by user.\n' not found in u'From cffi callback <function extern_clone_val at 0x11098a938>:\nTraceback (most recent call last):\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/native.py", line 427, in extern_clone_val\n    @ffi.def_extern()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/base/exception_sink.py", line 351, in handle_signal_gracefully\n    raise KeyboardInterrupt(\'User interrupted execution with control-c!\')\nKeyboardInterrupt: User interrupted execution with control-c!\ntimestamp: 2018-11-29T23:28:22.606384\nException caught: (pants.build_graph.address_lookup_error.AddressLookupError)\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 75, in <module>\n    main()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 71, in main\n    PantsLoader.run()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 67, in run\n    cls.load_and_execute(entrypoint)\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 60, in load_and_execute\n    entrypoint_main()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_exe.py", line 39, in main\n    PantsRunner(exiter, start_time=start_time).run()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_runner.py", line 62, in run\n    return runner.run()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 159, in run\n    self._run()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 227, in _run\n    goal_runner_result = self._maybe_run_v1(run_tracker, reporting)\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 176, in _maybe_run_v1\n    return goal_runner_factory.create().run()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/goal_runner.py", line 125, in create\n    goals, context = self._setup_context()\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/goal_runner.py", line 95, in _setup_context\n    self._root_dir\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/init/engine_initializer.py", line 226, in create_build_graph\n    for _ in graph.inject_roots_closure(target_roots):\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 217, in inject_roots_closure\n    for address in self._inject_specs(target_roots.specs):\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 270, in _inject_specs\n    subjects)\n  File "/usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 35, in __exit__\n    self.gen.throw(type, value, traceback)\n  File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 237, in _resolve_context\n    \'Build graph construction failed: {} {}\'.format(type(e).__name__, str(e))\n\nException message: Build graph construction failed: RuntimeError cannot use from_handle() on NULL pointer\n\n\n'

.pants.d/pyprep/sources/4d9f3a72ced4c3b5cabbfead9552e9e3e78a30ca/pants_test/base/test_exception_sink_integration.py:151: AssertionError
-------------- Captured stdout call --------------
logs/exceptions.84142.log +++
logs/exceptions.84142.log >>> timestamp: 2018-11-29T23:28:22.605908
logs/exceptions.84142.log >>> process title: python /Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py --no-pantsrc --pants-workdir=/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/tmpxqSksJ/.pants.d --kill-nailguns --print-exception-stacktrace=True --no-enable-pantsd run testprojects/src/python/coordinated_runs:waiter -- /var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/tmpxqSksJ/some_file
logs/exceptions.84142.log >>> sys.argv: ['/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py', '--no-pantsrc', '--pants-workdir=/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/tmpxqSksJ/.pants.d', '--kill-nailguns', '--print-exception-stacktrace=True', '--no-enable-pantsd', 'run', 'testprojects/src/python/coordinated_runs:waiter', '--', '/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/tmpxqSksJ/some_file']
logs/exceptions.84142.log >>> pid: 84142
logs/exceptions.84142.log >>> Exception caught: (pants.build_graph.address_lookup_error.AddressLookupError)
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 75, in <module>
logs/exceptions.84142.log >>> main()
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 71, in main
logs/exceptions.84142.log >>> PantsLoader.run()
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 67, in run
logs/exceptions.84142.log >>> cls.load_and_execute(entrypoint)
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 60, in load_and_execute
logs/exceptions.84142.log >>> entrypoint_main()
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_exe.py", line 39, in main
logs/exceptions.84142.log >>> PantsRunner(exiter, start_time=start_time).run()
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_runner.py", line 62, in run
logs/exceptions.84142.log >>> return runner.run()
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 159, in run
logs/exceptions.84142.log >>> self._run()
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 227, in _run
logs/exceptions.84142.log >>> goal_runner_result = self._maybe_run_v1(run_tracker, reporting)
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 176, in _maybe_run_v1
logs/exceptions.84142.log >>> return goal_runner_factory.create().run()
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/goal_runner.py", line 125, in create
logs/exceptions.84142.log >>> goals, context = self._setup_context()
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/goal_runner.py", line 95, in _setup_context
logs/exceptions.84142.log >>> self._root_dir
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/init/engine_initializer.py", line 226, in create_build_graph
logs/exceptions.84142.log >>> for _ in graph.inject_roots_closure(target_roots):
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 217, in inject_roots_closure
logs/exceptions.84142.log >>> for address in self._inject_specs(target_roots.specs):
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 270, in _inject_specs
logs/exceptions.84142.log >>> subjects)
logs/exceptions.84142.log >>> File "/usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 35, in __exit__
logs/exceptions.84142.log >>> self.gen.throw(type, value, traceback)
logs/exceptions.84142.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 237, in _resolve_context
logs/exceptions.84142.log >>> 'Build graph construction failed: {} {}'.format(type(e).__name__, str(e))
logs/exceptions.84142.log >>>
logs/exceptions.84142.log >>> Exception message: Build graph construction failed: RuntimeError cannot use from_handle() on NULL pointer
logs/exceptions.84142.log >>>
logs/exceptions.84142.log ---
logs/exceptions.log +++
logs/exceptions.log >>> timestamp: 2018-11-29T23:28:22.605908
logs/exceptions.log >>> process title: python /Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py --no-pantsrc --pants-workdir=/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/tmpxqSksJ/.pants.d --kill-nailguns --print-exception-stacktrace=True --no-enable-pantsd run testprojects/src/python/coordinated_runs:waiter -- /var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/tmpxqSksJ/some_file
logs/exceptions.log >>> sys.argv: ['/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py', '--no-pantsrc', '--pants-workdir=/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/tmpxqSksJ/.pants.d', '--kill-nailguns', '--print-exception-stacktrace=True', '--no-enable-pantsd', 'run', 'testprojects/src/python/coordinated_runs:waiter', '--', '/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/tmpxqSksJ/some_file']
logs/exceptions.log >>> pid: 84142
logs/exceptions.log >>> Exception caught: (pants.build_graph.address_lookup_error.AddressLookupError)
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 75, in <module>
logs/exceptions.log >>> main()
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 71, in main
logs/exceptions.log >>> PantsLoader.run()
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 67, in run
logs/exceptions.log >>> cls.load_and_execute(entrypoint)
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_loader.py", line 60, in load_and_execute
logs/exceptions.log >>> entrypoint_main()
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_exe.py", line 39, in main
logs/exceptions.log >>> PantsRunner(exiter, start_time=start_time).run()
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/pants_runner.py", line 62, in run
logs/exceptions.log >>> return runner.run()
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 159, in run
logs/exceptions.log >>> self._run()
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 227, in _run
logs/exceptions.log >>> goal_runner_result = self._maybe_run_v1(run_tracker, reporting)
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/local_pants_runner.py", line 176, in _maybe_run_v1
logs/exceptions.log >>> return goal_runner_factory.create().run()
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/goal_runner.py", line 125, in create
logs/exceptions.log >>> goals, context = self._setup_context()
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/bin/goal_runner.py", line 95, in _setup_context
logs/exceptions.log >>> self._root_dir
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/init/engine_initializer.py", line 226, in create_build_graph
logs/exceptions.log >>> for _ in graph.inject_roots_closure(target_roots):
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 217, in inject_roots_closure
logs/exceptions.log >>> for address in self._inject_specs(target_roots.specs):
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 270, in _inject_specs
logs/exceptions.log >>> subjects)
logs/exceptions.log >>> File "/usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 35, in __exit__
logs/exceptions.log >>> self.gen.throw(type, value, traceback)
logs/exceptions.log >>> File "/Users/travis/build/pantsbuild/pants/src/python/pants/engine/legacy/graph.py", line 237, in _resolve_context
logs/exceptions.log >>> 'Build graph construction failed: {} {}'.format(type(e).__name__, str(e))
logs/exceptions.log >>>
logs/exceptions.log >>> Exception message: Build graph construction failed: RuntimeError cannot use from_handle() on NULL pointer
logs/exceptions.log >>>
logs/exceptions.log ---
generated xml file: /Users/travis/build/pantsbuild/pants/.pants.d/test/pytest/tests.python.pants_test.base.exception_sink_integration/junitxml/TEST-tests.python.pants_test.base.exception_sink_integration.xml
============ slowest 3 test durations ============
93.67s call     ../tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_dumps_traceback_on_sigabrt
6.08s call     ../tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_prints_traceback_on_sigusr2
5.55s call     ../tests/python/pants_test/base/test_exception_sink_integration.py::ExceptionSinkIntegrationTest::test_reset_interactive_output_stream
1 failed, 5 passed, 1 skipped in 118.85 seconds =

# Fixed code
def reset_log_location(cls, new_log_location):
    """Re-acquire file handles to error logs based in the new location.

    Class state:
    - Overwrites `cls._log_dir`, `cls._pid_specific_error_fileobj`, and
      `cls._shared_error_fileobj`.
    OS state:
    - May create a new directory.
    - Overwrites signal handlers for many fatal and non-fatal signals.

    :raises: :class:`ExceptionSink.ExceptionSinkError` if the directory does not exist or is not
             writable.
    """
    # We could no-op here if the log locations are the same, but there's no reason not to have the
    # additional safety of re-acquiring file descriptors each time (and erroring out early if the
    # location is no longer writable).

    # Create the directory if possible, or raise if not writable.
    cls._check_or_create_new_destination(new_log_location)

    pid_specific_error_stream, shared_error_stream = (
        cls._recapture_fatal_error_log_streams(new_log_location)
    )

    # NB: mutate process-global state!
    if faulthandler.is_enabled():
        logger.debug("re-enabling faulthandler")
        # Call Py_CLEAR() on the previous error stream:
        # https://github.com/vstinner/faulthandler/blob/master/faulthandler.c
        faulthandler.disable()
    # Send a stacktrace to this file if interrupted by a fatal error.
    faulthandler.enable(file=pid_specific_error_stream, all_threads=True)

    # NB: mutate the class variables!
    cls._log_dir = new_log_location
    cls._pid_specific_error_fileobj = pid_specific_error_stream
    cls._shared_error_fileobj = shared_error_stream