diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/libpq/pqcomm.c | 6 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 12 | ||||
-rw-r--r-- | src/backend/utils/init/globals.c | 1 | ||||
-rw-r--r-- | src/include/miscadmin.h | 7 |
4 files changed, 25 insertions, 1 deletions
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index b83a2efb698..c36cf318267 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -1247,9 +1247,13 @@ internal_flush(void) /* * We drop the buffered data anyway so that processing can - * continue, even though we'll probably quit soon. + * continue, even though we'll probably quit soon. We also + * set a flag that'll cause the next CHECK_FOR_INTERRUPTS + * to terminate the connection. */ PqSendStart = PqSendPointer = 0; + ClientConnectionLost = 1; + InterruptPending = 1; return EOF; } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 976a832135e..5bb16e010cc 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -2823,6 +2823,18 @@ ProcessInterrupts(void) (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating connection due to administrator command"))); } + if (ClientConnectionLost) + { + QueryCancelPending = false; /* lost connection trumps QueryCancel */ + ImmediateInterruptOK = false; /* not idle anymore */ + DisableNotifyInterrupt(); + DisableCatchupInterrupt(); + /* don't send to client, we already know the connection to be dead. */ + whereToSendOutput = DestNone; + ereport(FATAL, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("connection to client lost"))); + } if (QueryCancelPending) { QueryCancelPending = false; diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 9ce64e67629..9417c7a3b04 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -29,6 +29,7 @@ ProtocolVersion FrontendProtocol; volatile bool InterruptPending = false; volatile bool QueryCancelPending = false; volatile bool ProcDiePending = false; +volatile bool ClientConnectionLost = false; volatile bool ImmediateInterruptOK = false; volatile uint32 InterruptHoldoffCount = 0; volatile uint32 CritSectionCount = 0; diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 4ee08fead6f..1df7723d995 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -55,6 +55,11 @@ * course, only if the interrupt holdoff counter is zero). See the * related code for details. * + * A lost connection is handled similarly, although the loss of connection + * does not raise a signal, but is detected when we fail to write to the + * socket. If there was a signal for a broken connection, we could make use of + * it by setting ClientConnectionLost in the signal handler. + * * A related, but conceptually distinct, mechanism is the "critical section" * mechanism. A critical section not only holds off cancel/die interrupts, * but causes any ereport(ERROR) or ereport(FATAL) to become ereport(PANIC) @@ -70,6 +75,8 @@ extern PGDLLIMPORT volatile bool InterruptPending; extern volatile bool QueryCancelPending; extern volatile bool ProcDiePending; +extern volatile bool ClientConnectionLost; + /* these are marked volatile because they are examined by signal handlers: */ extern volatile bool ImmediateInterruptOK; extern PGDLLIMPORT volatile uint32 InterruptHoldoffCount; |