Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit 889d35f

Browse files
committed
Merge pull request #2063 from rspec/stop-rescuing-all-exceptions
Stop rescuing all exceptions.
2 parents bb625ec + f2d40c1 commit 889d35f

File tree

6 files changed

+27
-11
lines changed

6 files changed

+27
-11
lines changed

.rubocop_rspec_base.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ Proc:
101101
RedundantReturn:
102102
AllowMultipleReturnValues: true
103103

104-
# We have to rescue Exception in the `raise_error` matcher for it to work properly.
104+
# Exceptions should be rescued with `Support::AllExceptionsExceptOnesWeMustNotRescue`
105105
RescueException:
106-
Enabled: false
106+
Enabled: true
107107

108108
# We haven't adopted the `fail` to signal exceptions vs `raise` for re-raises convention.
109109
SignalException:

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Enhancements:
2424
(Jon Rowe, #2052)
2525
* Append the root `cause` of a failure or error to the printed failure
2626
output when a `cause` is available. (Adam Magan)
27+
* Stop rescuing `NoMemoryError`, `SignalExcepetion`, `Interrupt` and
28+
`SystemExit`. It is dangerous to interfere with these. (Myron Marston, #2063)
2729

2830
Bug Fixes:
2931

lib/rspec/core/configuration.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1754,7 +1754,7 @@ def define_built_in_hooks
17541754
around(:example, :aggregate_failures => true) do |procsy|
17551755
begin
17561756
aggregate_failures(nil, :hide_backtrace => true, &procsy)
1757-
rescue Exception => exception
1757+
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => exception
17581758
procsy.example.set_aggregate_failures_exception(exception)
17591759
end
17601760
end

lib/rspec/core/example.rb

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,14 @@ def run(example_group_instance, reporter)
227227
rescue Pending::SkipDeclaredInExample
228228
# no-op, required metadata has already been set by the `skip`
229229
# method.
230-
rescue Exception => e
230+
rescue AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt => e
231231
set_exception(e)
232232
ensure
233233
run_after_example
234234
end
235235
end
236236
end
237-
rescue Exception => e
237+
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
238238
set_exception(e)
239239
ensure
240240
@example_group_instance = nil # if you love something... let it go
@@ -245,6 +245,20 @@ def run(example_group_instance, reporter)
245245
RSpec.current_example = nil
246246
end
247247

248+
if RSpec::Support::Ruby.jruby? || RUBY_VERSION.to_f < 1.9
249+
# :nocov:
250+
# For some reason, rescuing `Support::AllExceptionsExceptOnesWeMustNotRescue`
251+
# in place of `Exception` above can cause the exit status to be the wrong
252+
# thing. I have no idea why. See:
253+
# https://github.com/rspec/rspec-core/pull/2063#discussion_r38284978
254+
# @private
255+
AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt = Exception
256+
# :nocov:
257+
else
258+
# @private
259+
AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt = Support::AllExceptionsExceptOnesWeMustNotRescue
260+
end
261+
248262
# Wraps both a `Proc` and an {Example} for use in {Hooks#around
249263
# around} hooks. In around hooks we need to yield this special
250264
# kind of object (rather than the raw {Example}) because when
@@ -400,7 +414,7 @@ def hooks
400414

401415
def with_around_example_hooks
402416
hooks.run(:around, :example, self) { yield }
403-
rescue Exception => e
417+
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
404418
set_exception(e)
405419
end
406420

@@ -457,7 +471,7 @@ def run_after_example
457471

458472
def verify_mocks
459473
@example_group_instance.verify_mocks_for_rspec if mocks_need_verification?
460-
rescue Exception => e
474+
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
461475
set_exception(e)
462476
end
463477

@@ -476,7 +490,7 @@ def assign_generated_description
476490

477491
def generate_description
478492
RSpec::Matchers.generated_description
479-
rescue Exception => e
493+
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
480494
location_description + " (Got an error when generating description " \
481495
"from matcher: #{e.class}: #{e.message} -- #{e.backtrace.first})"
482496
end

lib/rspec/core/example_group.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ def self.run(reporter=RSpec::Core::NullReporter)
524524
rescue Pending::SkipDeclaredInExample => ex
525525
for_filtered_examples(reporter) { |example| example.skip_with_exception(reporter, ex) }
526526
true
527-
rescue Exception => ex
527+
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
528528
RSpec.world.wants_to_quit = true if fail_fast?
529529
for_filtered_examples(reporter) { |example| example.fail_with_exception(reporter, ex) }
530530
false

lib/rspec/core/hooks.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ def run(example)
362362
class AfterHook < Hook
363363
def run(example)
364364
example.instance_exec(example, &block)
365-
rescue Exception => ex
365+
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
366366
example.set_exception(ex)
367367
end
368368
end
@@ -371,7 +371,7 @@ def run(example)
371371
class AfterContextHook < Hook
372372
def run(example)
373373
example.instance_exec(example, &block)
374-
rescue Exception => e
374+
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
375375
# TODO: Come up with a better solution for this.
376376
RSpec.configuration.reporter.message <<-EOS
377377

0 commit comments

Comments
 (0)