summaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2015-02-23 13:32:34 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2015-02-23 13:32:39 +0200
commit0214a61e062f7d23d28e423850c20fc287d3f5e5 (patch)
tree3db7c574ab9822148a0551a4e930e3eb53b13e1a /doc/src
parent9c15a778a03d009883ec4370ac8b8d30d279aaa7 (diff)
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.
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/libpq.sgml9
1 files changed, 8 insertions, 1 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index d0fbd487f12..54dd71e03bf 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -4380,7 +4380,14 @@ int PQflush(PGconn *conn);
<para>
After sending any command or data on a nonblocking connection, call
<function>PQflush</function>. If it returns 1, wait for the socket
- to be write-ready and call it again; repeat until it returns 0. Once
+ to become read- or write-ready. If it becomes write-ready, call
+ <function>PQflush</function> again. If it becomes read-ready, call
+ <function>PQconsumeInput</function>, then call
+ <function>PQflush</function> again. Repeat until
+ <function>PQflush</function> returns 0. (It is necessary to check for
+ read-ready and drain the input with <function>PQconsumeInput</function>,
+ because the server can block trying to send us data, e.g. NOTICE
+ messages, and won't read our data until we read its.) Once
<function>PQflush</function> returns 0, wait for the socket to be
read-ready and then read the response as described above.
</para>