Skip to content

AsyncRedisManager: reconnect path orphans the previous Redis client without awaiting close #1569

Description

@zxzinn

AsyncRedisManager._redis_connect overwrites self.redis and self.pubsub without closing the previous ones. The old Redis client is never awaited closed, so its TCP socket (and TLS session for rediss://) is leaked.

redis.asyncio.Redis requires await aclose() for cleanup; its __del__ only emits ResourceWarning: Unclosed client session because async cleanup cannot run in __del__. The manager owns the client, so the manager must close it.

_redis_connect runs on every reconnect:

  • _publish calls it after a failed publish
  • _redis_listen_with_retries calls it after any RedisError

Under sustained Redis pressure these fire repeatedly, leaking one socket per reconnect.

Repro: https://github.com/zxzinn/python-socketio-redis-leak-repro

warmup        sockets=1
reconnect #1  sockets=2
reconnect #2  sockets=3
reconnect #3  sockets=4
reconnect #4  sockets=5
reconnect #5  sockets=6

Each iteration emits ResourceWarning: unclosed Connection.

Fix: await self.pubsub.aclose() and await self.redis.aclose() before reassigning. _redis_connect is sync today but both callers are already async.

Reproduces on 5.16.1 and 5.8.0.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions