Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7052abb

Browse files
committed
Fix potential deadlock with libpq non-blocking mode.
If libpq output buffer is full, pqSendSome() function tries to drain anyincoming data. This avoids deadlock, if the server e.g. sends a lot ofNOTICE messages, and blocks until we read them. However, pqSendSome() onlydid that in blocking mode. In non-blocking mode, the deadlock could stillhappen.To fix, take a two-pronged approach:1. Change the documentation to instruct that when PQflush() returns 1, youshould wait for both read- and write-ready, and call PQconsumeInput() if itbecomes read-ready. That fixes the deadlock, but applications are not goingto change overnight.2. In pqSendSome(), drain the input buffer before returning 1. Thisalleviates the problem for applications that only wait for write-ready. Inparticular, a slow but steady stream of NOTICE messages during COPY FROMSTDIN will no longer cause a deadlock. The risk remains that the serverattempts to send a large burst of data and fills its output buffer, and atthe 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 socketto become write-ready, before the server's data arrives. In practice,NOTICE messages and such that the server might be sending are usuallyshort, so it's highly unlikely that the server would fill its output bufferso quickly.Backpatch to all supported versions.
1 parentb0d53b2 commit7052abb

File tree

2 files changed

+25
-11
lines changed

2 files changed

+25
-11
lines changed

‎doc/src/sgml/libpq.sgml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4084,7 +4084,14 @@ int PQflush(PGconn *conn);
40844084
<para>
40854085
After sending any command or data on a nonblocking connection, call
40864086
<function>PQflush</function>. If it returns 1, wait for the socket
4087-
to be write-ready and call it again; repeat until it returns 0. Once
4087+
to become read- or write-ready. If it becomes write-ready, call
4088+
<function>PQflush</function> again. If it becomes read-ready, call
4089+
<function>PQconsumeInput</function>, then call
4090+
<function>PQflush</function> again. Repeat until
4091+
<function>PQflush</function> returns 0. (It is necessary to check for
4092+
read-ready and drain the input with <function>PQconsumeInput</function>,
4093+
because the server can block trying to send us data, e.g. NOTICE
4094+
messages, and won't read our data until we read its.) Once
40884095
<function>PQflush</function> returns 0, wait for the socket to be
40894096
read-ready and then read the response as described above.
40904097
</para>

‎src/interfaces/libpq/fe-misc.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -882,16 +882,6 @@ pqSendSome(PGconn *conn, int len)
882882
/*
883883
* We didn't send it all, wait till we can send more.
884884
*
885-
* If the connection is in non-blocking mode we don't wait, but
886-
* return 1 to indicate that data is still pending.
887-
*/
888-
if (pqIsnonblocking(conn))
889-
{
890-
result=1;
891-
break;
892-
}
893-
894-
/*
895885
* There are scenarios in which we can't send data because the
896886
* communications channel is full, but we cannot expect the server
897887
* to clear the channel eventually because it's blocked trying to
@@ -902,12 +892,29 @@ pqSendSome(PGconn *conn, int len)
902892
* again. Furthermore, it is possible that such incoming data
903893
* might not arrive until after we've gone to sleep. Therefore,
904894
* we wait for either read ready or write ready.
895+
*
896+
* In non-blocking mode, we don't wait here directly, but return
897+
* 1 to indicate that data is still pending. The caller should
898+
* wait for both read and write ready conditions, and call
899+
* PQconsumeInput() on read ready, but just in case it doesn't, we
900+
* call pqReadData() ourselves before returning. That's not
901+
* enough if the data has not arrived yet, but it's the best we
902+
* can do, and works pretty well in practice. (The documentation
903+
* used to say that you only need to wait for write-ready, so
904+
* there are still plenty of applications like that out there.)
905905
*/
906906
if (pqReadData(conn)<0)
907907
{
908908
result=-1;/* error message already set up */
909909
break;
910910
}
911+
912+
if (pqIsnonblocking(conn))
913+
{
914+
result=1;
915+
break;
916+
}
917+
911918
if (pqWait(TRUE, TRUE,conn))
912919
{
913920
result=-1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp