#36957: Django psycopg connection pool + fork()
---------------------+-----------------------------------------
     Reporter:  doc  |                     Type:  Bug
       Status:  new  |                Component:  Uncategorized
      Version:  6.0  |                 Severity:  Normal
     Keywords:       |             Triage Stage:  Unreviewed
    Has patch:  0    |      Needs documentation:  0
  Needs tests:  0    |  Patch needs improvement:  0
Easy pickings:  0    |                    UI/UX:  0
---------------------+-----------------------------------------
 Django's PostgreSQL backend stores psycopg_pool.ConnectionPool objects in
 a class-level dict (DatabaseWrapper._connection_pools). When gunicorn (or
 any pre-forking server) forks worker processes, all children inherit
 references to the same pool objects — and crucially, the same underlying
 TCP sockets to PostgreSQL. Multiple workers then read/write the same
 socket concurrently, corrupting the PostgreSQL wire protocol.


 **Root cause**

 {{{
 # django/db/backends/postgresql/base.py
 class DatabaseWrapper(BaseDatabaseWrapper):
     _connection_pools = {}   # class-level dict — survives fork()

     @property
     def pool(self):
         if self.alias not in self._connection_pools:
             pool = ConnectionPool(...)
             self._connection_pools.setdefault(self.alias, pool)
         return self._connection_pools[self.alias]
 }}}

 **Workaround**

 {{{
 # gunicorn.conf.py
 def post_fork(server, worker):
     from django.db.backends.postgresql.base import DatabaseWrapper
     DatabaseWrapper._connection_pools.clear()
 }}}

 **Suggested fix**
 Use `os.register_at_fork(after_in_child=...)` to clear `_connection_pools`
 in child processes, or check `os.getpid()` in the `pool` property and
 recreate when it differs from the creating process.

 **Tested with**
 Django 6.0.2
 psycopg 3.2.x – 3.3.2
 psycopg-pool 3.2.x – 3.3.0
 gunicorn 25.x (--worker-class asgi)
 Python 3.12 – 3.14
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36957>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/0107019c9e7f81cb-518548b0-645d-4a2c-9dc8-342dea436cbc-000000%40eu-central-1.amazonses.com.

Reply via email to