-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
AttributeError: 'NoneType' object has no attribute 'close' #1345
Comments
I've been digging into this for a bit this afternoon. I didn't write redis-py's sentinel implementation so this is a good exercise for me to become more familiar with what's happening. First, a question: Are you calling Here are some observations after reading the code.
If we fix item 2, there will still be a hiccup when the new master is elected, but then all the clients should get connected to the new master and work correctly. |
Hi Andy,
I'm just calling
Yep. Clients have to deal with various errors here (mostly timeout and connection errors). However, since
I haven't found a good way to safely disconnect in-use connections in the pool other than using a generation id and reaping them when they are released back to the pool. Clients expect to deal with normal network and service outage errors, but they shouldn't have to be dealing with If it's helpful, I can post my patch that I'm using to fix the
Ah, I forgot PR #847 hasn't been merged into master yet. I have that merged into my tree. It fixes that problem :) |
Merged #847 as that clearly needed to be fixed. If you want to post what you have for the generation ID stuff I'll take a look. |
Great. Patch is attached, very simple. |
@rolette I pushed the https://github.com/andymccurdy/redis-py/tree/sentinel-1345 branch that I believe fixes this. It uses a slightly different approach as your solution, but I believe it results in the same basic behavior of throwing a stale connection out when it's returned to the pool. It also fixes a bug where the base |
@andymccurdy Reviewed your changes and added my $0.02. Thanks! |
@rolette I added an optional When the Have I missed anything? |
@andymccurdy I'd make Have I missed anything? |
@rolette I made I am calling |
@andymccurdy Ok, that looks good. Appreciate the fixes! |
Great, I'll merge this and release 3.5.3 |
Just released 3.5.3 with this fix. |
Unfortunately, the fix for #732 doesn't correctly handle master node failover for multi-threaded code.
Scenario is this:
SentinelConnectionPool
to get their separate connections to the Redis masterSentinelConnectionPool.get_master_address()
get_master_address()
notices that there is a new master and callsself.disconnect()
to flush the poolConnectionPool.disconnect()
callsdisconnect()
on each of the connections in the pool.Connection.disconnect()
sees a matching PID and callsshutdown()
on the socket, then sets it back toNone
There is thread-locking to protect the pool's management of its members, but
ConnectionPool.disconnect()
is ripping sockets out from other threads in the middle of other operations.The actual stack trace and error you'll get will vary depending on timing.
To fix it in my product code, I'm re-integrating the deferred disconnect using a generation id from PR #784.
Version: redis-py v3.4.1, redis/sentinel v3.2.13
Platform: Python 3.5.2 on Linux
The text was updated successfully, but these errors were encountered: