redis-py icon indicating copy to clipboard operation
redis-py copied to clipboard

Catch `Exception` and not `BaseException` in the `Connection`

Open kristjanvalur opened this issue 3 years ago • 11 comments

Pull Request check-list

Please make sure to review and check all of these items:

  • [x] Does $ tox pass with this change (including linting)?
  • [x] Do the CI tests pass with this change (enable it first in your forked repo and wait for the github action build to finish)?
  • [x] Is the new or changed code fully tested?
  • [ ] Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?
  • [ ] Is there an example added to the examples folder (if applicable)?
  • [x] Was the change added to CHANGES file?

Description of change

Fixes Issue #2103: Raising a BaseException inside a Connection's send or receive oprations causes a disconnect(). BaseExceptions are commonly used for out of band messages in Python and normally not be expecially acted upon, only be handled at the top-level

kristjanvalur avatar Apr 13 '22 11:04 kristjanvalur

Codecov Report

Merging #2104 (e482225) into master (b5ebada) will decrease coverage by 0.00%. The diff coverage is 92.59%.

@@            Coverage Diff             @@
##           master    #2104      +/-   ##
==========================================
- Coverage   92.21%   92.20%   -0.01%     
==========================================
  Files         111      111              
  Lines       28781    28853      +72     
==========================================
+ Hits        26539    26605      +66     
- Misses       2242     2248       +6     
Impacted Files Coverage Δ
redis/asyncio/connection.py 85.84% <50.00%> (-0.28%) :arrow_down:
redis/connection.py 86.90% <50.00%> (ø)
tests/test_asyncio/test_pubsub.py 99.52% <100.00%> (+0.20%) :arrow_up:
tests/test_pubsub.py 99.61% <100.00%> (+0.01%) :arrow_up:
tests/test_timeseries.py 100.00% <100.00%> (ø)
tests/test_cluster.py 96.85% <0.00%> (-0.24%) :arrow_down:

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

codecov-commenter avatar Apr 13 '22 11:04 codecov-commenter

@kristjanvalur Why did you catch Exception rather that BaseException? Was there an inheritance issue you saw?

chayim avatar Apr 24 '22 14:04 chayim

@chayim have a look here #2103

WisdomPill avatar Apr 24 '22 14:04 WisdomPill

I can add tests. As I explained in the defect, BaseException is usually not caught except in top level handlers, unless it is to implement something like async_timeout.Timeout() . BaseException was added to Python precisely to be a sort of meta exception that regular exception handling doesn't touch, the Exception being the most general class usually touched in code that isn't trying to be too clever.

kristjanvalur avatar Apr 25 '22 09:04 kristjanvalur

In fact, I don't see why there is a except Exception: self.disconnect(); raise at all. Doesn't seem like something the Connection should do if it gets an unexpected exception. IMHO, this clause should be removed alltogether.

kristjanvalur avatar Apr 25 '22 13:04 kristjanvalur

(There isn't an equivalent non-async test that can be easily done, without writing a thread-based timeout class.)

kristjanvalur avatar Apr 25 '22 13:04 kristjanvalur

Hm, now it is mysteriously failing. it asserts on the "assert pubsub.connection.is_connected" I´m running tests both on windows and in a linux dev container using pytest tests/test_async/test_pubsub.py. I don't get the test failures above.

kristjanvalur avatar Apr 25 '22 17:04 kristjanvalur

Well, it seems I cracked the unittest problem I was having. Turned out that only in Python 3.8 did asyncio.CancelledError get promoted to BaseException. Fixed up the test to skip older python versions and added Mock-based tests for exception propagation for both async and blocking redis.

kristjanvalur avatar Jun 24 '22 15:06 kristjanvalur

any responses? @WisdomPill ?

kristjanvalur avatar Jul 09 '22 11:07 kristjanvalur

I'll clean up the commit history a bit...

kristjanvalur avatar Jul 09 '22 11:07 kristjanvalur

yet another fluke test failure.

kristjanvalur avatar Jul 09 '22 11:07 kristjanvalur

I bumped into this too – trying to e.g. ctrl+c out of py.test requires a couple of tries because KeyboardInterrupt (a BaseException) is caught where it really must not be.

akx avatar Sep 19 '22 11:09 akx

woo-hoo!

kristjanvalur avatar Sep 29 '22 11:09 kristjanvalur

Thanks for this! And sorry this (and your other PR's) waited so long...

dvora-h avatar Sep 29 '22 11:09 dvora-h