summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/libpq/fe-secure.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 847f2721dd8..a07c44ad14b 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -1430,13 +1430,22 @@ open_client_SSL(PGconn *conn)
static void
close_SSL(PGconn *conn)
{
+ bool destroy_needed = false;
+
if (conn->ssl)
{
DISABLE_SIGPIPE((void) 0);
+
+ /*
+ * We can't destroy everything SSL-related here due to the possible
+ * later calls to OpenSSL routines which may need our thread
+ * callbacks, so set a flag here and check at the end.
+ */
+ destroy_needed = true;
+
SSL_shutdown(conn->ssl);
SSL_free(conn->ssl);
conn->ssl = NULL;
- pqsecure_destroy();
/* We have to assume we got EPIPE */
REMEMBER_EPIPE(true);
RESTORE_SIGPIPE();
@@ -1456,6 +1465,17 @@ close_SSL(PGconn *conn)
conn->engine = NULL;
}
#endif
+
+ /*
+ * This will remove our SSL locking hooks, if this is the last SSL
+ * connection, which means we must wait to call it until after all
+ * SSL calls have been made, otherwise we can end up with a race
+ * condition and possible deadlocks.
+ *
+ * See comments above destroy_ssl_system().
+ */
+ if (destroy_needed)
+ pqsecure_destroy();
}
/*