0004-Heavily-WIP-Process-die-interrupts-while-reading-wri.patch
text/x-patch
Filename: 0004-Heavily-WIP-Process-die-interrupts-while-reading-wri.patch
Type: text/x-patch
Part: 3
Patch
Format: unified
Series: patch 0004
| File | + | − |
|---|---|---|
| src/backend/libpq/be-secure.c | 20 | 3 |
| src/backend/libpq/be-secure-openssl.c | 6 | 1 |
| src/backend/tcop/postgres.c | 25 | 0 |
| src/include/tcop/tcopprot.h | 1 | 0 |
>From 222254b14be455e750fd84be3a017a3c47d3f384 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sun, 28 Sep 2014 00:22:39 +0200
Subject: [PATCH 4/4] Heavily-WIP: Process 'die' interrupts while
reading/writing from a socket.
Per discussion with Kyotaro HORIGUCHI and Heikki Linnakangas
---
src/backend/libpq/be-secure-openssl.c | 7 ++++++-
src/backend/libpq/be-secure.c | 23 ++++++++++++++++++++---
src/backend/tcop/postgres.c | 25 +++++++++++++++++++++++++
src/include/tcop/tcopprot.h | 1 +
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 6fc6903..22e2a7b 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -638,7 +638,12 @@ wloop:
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
- /* XXX: We likely will want to process some interrupts here */
+ /*
+ * Check for interrupts here, in addition to secure_write(),
+ * because a interrupted write in secure_raw_write() will only
+ * return here, not secure_write().
+ */
+ ProcessClientWriteInterrupt(err == SSL_ERROR_WANT_WRITE);
if (port->noblock)
{
errno = EWOULDBLOCK;
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index 7b5b30f..6831dd8 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -199,6 +199,7 @@ secure_write(Port *port, void *ptr, size_t len)
{
ssize_t n;
+retry:
#ifdef USE_SSL
if (port->ssl_in_use)
{
@@ -210,7 +211,14 @@ secure_write(Port *port, void *ptr, size_t len)
n = secure_raw_write(port, ptr, len);
}
- /* XXX: We likely will want to process some interrupts here */
+ /* Process interrupts that happened while (or before) writing. */
+ ProcessClientWriteInterrupt(!port->noblock && n < 0);
+
+ /* retry after processing interrupts */
+ if (n < 0 && errno == EINTR)
+ {
+ goto retry;
+ }
return n;
}
@@ -236,10 +244,19 @@ wloop:
* don't do anything while (possibly) inside a ssl library.
*/
w = WaitLatchOrSocket(&MyProc->procLatch,
- WL_SOCKET_WRITEABLE,
+ WL_LATCH_SET | WL_SOCKET_WRITEABLE,
port->sock, 0);
- if (w & WL_SOCKET_WRITEABLE)
+ if (w & WL_LATCH_SET)
+ {
+ ResetLatch(&MyProc->procLatch);
+ /*
+ * Force a return, so interrupts can be processed when not
+ * (possibly) underneath a ssl library.
+ */
+ errno = EINTR;
+ }
+ else if (w & WL_SOCKET_WRITEABLE)
{
goto wloop;
}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 3a6aa1c..ffc7822 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -520,8 +520,33 @@ ProcessClientReadInterrupt(void)
errno = save_errno;
}
+ else if (ProcDiePending)
+ {
+ /*
+ * We're dying. It's safe (and sane) to handle that now.
+ */
+ CHECK_FOR_INTERRUPTS();
+ }
}
+void
+ProcessClientWriteInterrupt(bool blocked)
+{
+ /*
+ * We only want to process the interrupt here if socket writes are
+ * blocking to increase the chance to get an error message to the
+ * client. If we're not blocked there'll soon be a
+ * CHECK_FOR_INTERRUPTS(). But if we're blocked we'll never get out of
+ * that situation if the client has died.
+ */
+ if (ProcDiePending && blocked)
+ {
+ /*
+ * We're dying. It's safe (and sane) to handle that now.
+ */
+ CHECK_FOR_INTERRUPTS();
+ }
+}
/*
* Do raw parsing (only).
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index e4a1a7d..d3db716 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -68,6 +68,7 @@ extern void FloatExceptionHandler(SIGNAL_ARGS) __attribute__((noreturn));
extern void RecoveryConflictInterrupt(ProcSignalReason reason); /* called from SIGUSR1
* handler */
extern void ProcessClientReadInterrupt(void);
+extern void ProcessClientWriteInterrupt(bool blocked);
extern void process_postgres_switches(int argc, char *argv[],
GucContext ctx, const char **dbname);
--
1.8.3.251.g1462b67