missing NOTIFY events in async mode

From: Jan Urbański <wulczer(at)wulczer(dot)org>
To: psycopg(at)postgresql(dot)org
Cc: mwalton(at)evertz(dot)com
Subject: missing NOTIFY events in async mode
Date: 2014-06-23 17:10:58
Message-ID: 53A85FA2.50605@wulczer.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: psycopg

Hi,

I got a bug report for txpostgres about NOTIFY events being missed if a
large number of events were sent at the same time. After investigating,
I believe it's a psycopg bug causing the behaviour.

Commit d9c0b8166f9ba17eacb09d5861409ab862447331 removed
conn_notifies_process from pq_fetch for what I guess were good reasons.
The problem is that the async execution patch will call pq_fetch after
an asynchronous query is finished and any notifies received at that
point will not be exposed to the application until the next poll() cycle.

What actually happens is that conn_poll calls _conn_poll_query, which
then calls pq_is_busy. That will check for notifies, but only the ones
that have already been received on the socket at that time. With enough
notifies to span several TCP packets, some of them will remain unread by
the client. Note that the result of _conn_poll_query will be
PSYCO_POLL_OK anyway.

conn_poll then continues to call pq_get_last_result, which calls down to
PQgetResult, causing the remainder of the data to be read from the
socket, along with the pending notifies. However, they won't be parsed
and made available on the Python Connection object.

Attached is a patch that solved the problem for me and a test case that
demonstrates how the connection is missing notifies.

I'm not 100% sure if that's the correct place to put a
conn_notifies_process() call - perhaps it should be in conn_poll inside
the block starting with:

if (res == PSYCO_POLL_OK && self->async && self->async_cursor) {

In any case, it should have a C comment attached, but as I wasn't sure
if the fix is in the right place, I haven't added one yet.

Credit for reporting the bug and preparing the initial test case goes to
Max Walton, which I have taken the liberty of CC'ing.

As an aside: what's the correct process for sending patches to Psycopg?
I see that tickets are tracked in Lighthouse, but the project is still
taking pull requests on GitHub?

Best,
Jan

Attachment Content-Type Size
psycopg-missed-notify.py text/x-python 792 bytes
psycopg-missed-notify.patch text/x-patch 283 bytes

Browse psycopg by date

  From Date Subject
Next Message Will Platnick 2014-07-07 13:27:40 Psycopg2 unable to timeout
Previous Message Rory Campbell-Lange 2014-06-18 16:10:19 Re: Problems with listen / notify