Skip to content
Snippets Groups Projects
Commit 3a9e64aa authored by Heikki Linnakangas's avatar Heikki Linnakangas
Browse files

Cannot use WL_SOCKET_WRITEABLE without WL_SOCKET_READABLE.

In copy-out mode, the frontend should not send any messages until the
backend has finished streaming, by sending a CopyDone message. I'm not sure
if it would be legal for the client to send a new query before receiving the
CopyDone message from the backend, but trying to support that would require
bigger changes to the backend code structure.

Fixes an assertion failure reported by Fujii Masao.
parent 5ddf38f2
No related branches found
No related tags found
No related merge requests found
...@@ -674,12 +674,7 @@ ProcessRepliesIfAny(void) ...@@ -674,12 +674,7 @@ ProcessRepliesIfAny(void)
int r; int r;
bool received = false; bool received = false;
/* for (;;)
* If we already received a CopyDone from the frontend, any subsequent
* message is the beginning of a new command, and should be processed in
* the main processing loop.
*/
while (!streamingDoneReceiving)
{ {
r = pq_getbyte_if_available(&firstchar); r = pq_getbyte_if_available(&firstchar);
if (r < 0) if (r < 0)
...@@ -696,6 +691,19 @@ ProcessRepliesIfAny(void) ...@@ -696,6 +691,19 @@ ProcessRepliesIfAny(void)
break; break;
} }
/*
* If we already received a CopyDone from the frontend, the frontend
* should not send us anything until we've closed our end of the COPY.
* XXX: In theory, the frontend could already send the next command
* before receiving the CopyDone, but libpq doesn't currently allow
* that.
*/
if (streamingDoneReceiving && firstchar != 'X')
ereport(FATAL,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("unexpected standby message type \"%c\", after receiving CopyDone",
firstchar)));
/* 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)
{ {
...@@ -1048,10 +1056,8 @@ WalSndLoop(void) ...@@ -1048,10 +1056,8 @@ WalSndLoop(void)
long sleeptime = 10000; /* 10 s */ long sleeptime = 10000; /* 10 s */
int wakeEvents; int wakeEvents;
wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_TIMEOUT; wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_TIMEOUT |
WL_SOCKET_READABLE;
if (!streamingDoneReceiving)
wakeEvents |= WL_SOCKET_READABLE;
if (pq_is_send_pending()) if (pq_is_send_pending())
wakeEvents |= WL_SOCKET_WRITEABLE; wakeEvents |= WL_SOCKET_WRITEABLE;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment