There is a race between Pool.return_socket and Pool.reset that can cause the pool to return connections from previous generations (pool_id).
- Assume the current pool generation is 1.
- Thread A calls pool.return_socket to return a connection with generation 1 and pauses while attempting to acquire the lock: https://github.com/mongodb/mongo-python-driver/blob/3.10.1/pymongo/pool.py#L1224
- Thread B calls pool.reset which clears the pool and increments the generation to 2.
- Thread A resumes execution, acquires the lock, and adds the connection (with generation 1) to the pool: https://github.com/mongodb/mongo-python-driver/blob/3.10.1/pymongo/pool.py#L1225
- The pool with generation 2 now has a connection with generation 1.
- A subsequent checkout will return the stale connection.
- Fix the race condition by checking the generation after acquiring the lock in pool.return_socket.
- And a sanity check that discards stale connections during checkout.