Commit 3e87ba6e authored by Heikki Linnakangas's avatar Heikki Linnakangas

Fix pq_getbyte_if_available() function. It was confused on what it

returns if no data is immediately available. Patch by me with numerous
fixes from Fujii Masao and Magnus Hagander.
parent 1a1ad632
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.96 2010/01/15 09:19:02 heikki Exp $ * $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.97 2010/02/18 11:13:45 heikki Exp $
* *
* Since the server static private key ($DataDir/server.key) * Since the server static private key ($DataDir/server.key)
* will normally be stored unencrypted so that the database * will normally be stored unencrypted so that the database
...@@ -256,7 +256,11 @@ rloop: ...@@ -256,7 +256,11 @@ rloop:
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
if (port->noblock) if (port->noblock)
return 0; {
errno = EWOULDBLOCK;
n = -1;
break;
}
#ifdef WIN32 #ifdef WIN32
pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl), pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
(err == SSL_ERROR_WANT_READ) ? (err == SSL_ERROR_WANT_READ) ?
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.203 2010/02/16 19:26:02 mha Exp $ * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.204 2010/02/18 11:13:45 heikki Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -821,8 +821,8 @@ pq_peekbyte(void) ...@@ -821,8 +821,8 @@ pq_peekbyte(void)
* pq_getbyte_if_available - get a single byte from connection, * pq_getbyte_if_available - get a single byte from connection,
* if available * if available
* *
* The received byte is stored in *c. Returns 1 if a byte was read, 0 if * The received byte is stored in *c. Returns 1 if a byte was read,
* if no data was available, or EOF. * 0 if no data was available, or EOF if trouble.
* -------------------------------- * --------------------------------
*/ */
int int
...@@ -848,6 +848,33 @@ pq_getbyte_if_available(unsigned char *c) ...@@ -848,6 +848,33 @@ pq_getbyte_if_available(unsigned char *c)
PG_TRY(); PG_TRY();
{ {
r = secure_read(MyProcPort, c, 1); r = secure_read(MyProcPort, c, 1);
if (r < 0)
{
/*
* Ok if no data available without blocking or interrupted
* (though EINTR really shouldn't happen with a non-blocking
* socket). Report other errors.
*/
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
r = 0;
else
{
/*
* Careful: an ereport() that tries to write to the client would
* cause recursion to here, leading to stack overflow and core
* dump! This message must go *only* to the postmaster log.
*/
ereport(COMMERROR,
(errcode_for_socket_access(),
errmsg("could not receive data from client: %m")));
r = EOF;
}
}
else if (r == 0)
{
/* EOF detected */
r = EOF;
}
} }
PG_CATCH(); PG_CATCH();
{ {
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/replication/walsender.c,v 1.6 2010/02/17 04:19:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/replication/walsender.c,v 1.7 2010/02/18 11:13:46 heikki Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -176,14 +176,7 @@ WalSndHandshake(void) ...@@ -176,14 +176,7 @@ WalSndHandshake(void)
ProcessConfigFile(PGC_SIGHUP); ProcessConfigFile(PGC_SIGHUP);
} }
if (firstchar == EOF) if (firstchar != EOF)
{
/* standby disconnected */
ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("unexpected EOF on standby connection")));
}
else
{ {
/* /*
* Read the message contents. This is expected to be done without * Read the message contents. This is expected to be done without
...@@ -193,9 +186,7 @@ WalSndHandshake(void) ...@@ -193,9 +186,7 @@ WalSndHandshake(void)
firstchar = EOF; /* suitable message already logged */ firstchar = EOF; /* suitable message already logged */
} }
/* Handle the very limited subset of commands expected in this phase */ /* Handle the very limited subset of commands expected in this phase */
switch (firstchar) switch (firstchar)
{ {
case 'Q': /* Query message */ case 'Q': /* Query message */
...@@ -286,14 +277,16 @@ WalSndHandshake(void) ...@@ -286,14 +277,16 @@ WalSndHandshake(void)
break; break;
} }
/* 'X' means that the standby is closing the connection */
case 'X': case 'X':
/* standby is closing the connection */
proc_exit(0); proc_exit(0);
case EOF: case EOF:
ereport(ERROR, /* standby disconnected unexpectedly */
ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION), (errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("unexpected EOF on standby connection"))); errmsg("unexpected EOF on standby connection")));
proc_exit(0);
default: default:
ereport(FATAL, ereport(FATAL,
...@@ -315,36 +308,23 @@ CheckClosedConnection(void) ...@@ -315,36 +308,23 @@ CheckClosedConnection(void)
r = pq_getbyte_if_available(&firstchar); r = pq_getbyte_if_available(&firstchar);
if (r < 0) if (r < 0)
{ {
/* no data available */ /* unexpected error or EOF */
if (errno == EAGAIN || errno == EWOULDBLOCK)
return;
/*
* Ok if interrupted, though it shouldn't really happen with
* a non-blocking operation.
*/
if (errno == EINTR)
return;
ereport(COMMERROR, ereport(COMMERROR,
(errcode_for_socket_access(), (errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("could not receive data from client: %m"))); errmsg("unexpected EOF on standby connection")));
proc_exit(0);
} }
if (r == 0) if (r == 0)
{ {
/* standby disconnected unexpectedly */ /* no data available without blocking */
ereport(ERROR, return;
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("unexpected EOF on standby connection")));
} }
/* Handle the very limited subset of commands expected in this phase */ /* Handle the very limited subset of commands expected in this phase */
switch (firstchar) switch (firstchar)
{ {
/* /*
* 'X' means that the standby is closing down the socket. EOF means * 'X' means that the standby is closing down the socket.
* unexpected loss of standby connection. Either way, perform normal
* shutdown.
*/ */
case 'X': case 'X':
proc_exit(0); proc_exit(0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment