Skip to content
Snippets Groups Projects
Commit 9dfdbef3 authored by Tom Lane's avatar Tom Lane
Browse files

Adjust libpq to avoid deadlock when both client and server want to send

data, and both have filled the transmission buffers.  One scenario where
this can happen was illustrated here:
http://archives.postgresql.org/pgsql-hackers/2003-04/msg00979.php
parent d5353acb
No related branches found
No related tags found
No related merge requests found
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.151 2003/10/04 21:05:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.152 2003/10/19 21:36:41 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1336,6 +1336,17 @@ PQputCopyData(PGconn *conn, const char *buffer, int nbytes) ...@@ -1336,6 +1336,17 @@ PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
libpq_gettext("no COPY in progress\n")); libpq_gettext("no COPY in progress\n"));
return -1; return -1;
} }
/*
* Check for NOTICE messages coming back from the server. Since the
* server might generate multiple notices during the COPY, we have to
* consume those in a reasonably prompt fashion to prevent the comm
* buffers from filling up and possibly blocking the server.
*/
if (!PQconsumeInput(conn))
return -1; /* I/O failure */
parseInput(conn);
if (nbytes > 0) if (nbytes > 0)
{ {
/* /*
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.102 2003/08/08 21:42:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.103 2003/10/19 21:36:41 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -828,7 +828,24 @@ pqSendSome(PGconn *conn, int len) ...@@ -828,7 +828,24 @@ pqSendSome(PGconn *conn, int len)
break; break;
} }
if (pqWait(FALSE, TRUE, conn)) /*
* There are scenarios in which we can't send data because the
* communications channel is full, but we cannot expect the server
* to clear the channel eventually because it's blocked trying to
* send data to us. (This can happen when we are sending a large
* amount of COPY data, and the server has generated lots of
* NOTICE responses.) To avoid a deadlock situation, we must be
* prepared to accept and buffer incoming data before we try
* again. Furthermore, it is possible that such incoming data
* might not arrive until after we've gone to sleep. Therefore,
* we wait for either read ready or write ready.
*/
if (pqReadData(conn) < 0)
{
result = -1; /* error message already set up */
break;
}
if (pqWait(TRUE, TRUE, conn))
{ {
result = -1; result = -1;
break; break;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment