]> granicus.if.org Git - postgresql/commit
Fix potential deadlock with libpq non-blocking mode.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 23 Feb 2015 11:32:34 +0000 (13:32 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 23 Feb 2015 11:32:39 +0000 (13:32 +0200)
commit0214a61e062f7d23d28e423850c20fc287d3f5e5
tree3db7c574ab9822148a0551a4e930e3eb53b13e1a
parent9c15a778a03d009883ec4370ac8b8d30d279aaa7
Fix potential deadlock with libpq non-blocking mode.

If libpq output buffer is full, pqSendSome() function tries to drain any
incoming data. This avoids deadlock, if the server e.g. sends a lot of
NOTICE messages, and blocks until we read them. However, pqSendSome() only
did that in blocking mode. In non-blocking mode, the deadlock could still
happen.

To fix, take a two-pronged approach:

1. Change the documentation to instruct that when PQflush() returns 1, you
should wait for both read- and write-ready, and call PQconsumeInput() if it
becomes read-ready. That fixes the deadlock, but applications are not going
to change overnight.

2. In pqSendSome(), drain the input buffer before returning 1. This
alleviates the problem for applications that only wait for write-ready. In
particular, a slow but steady stream of NOTICE messages during COPY FROM
STDIN will no longer cause a deadlock. The risk remains that the server
attempts to send a large burst of data and fills its output buffer, and at
the same time the client also sends enough data to fill its output buffer.
The application will deadlock if it goes to sleep, waiting for the socket
to become write-ready, before the server's data arrives. In practice,
NOTICE messages and such that the server might be sending are usually
short, so it's highly unlikely that the server would fill its output buffer
so quickly.

Backpatch to all supported versions.
doc/src/sgml/libpq.sgml
src/interfaces/libpq/fe-misc.c