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
This commit is contained in:
parent
d5353acbc3
commit
9dfdbef345
@ -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)
|
|||||||
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 @@
|
|||||||
* 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)
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user