aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/libpq/fe-secure.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 3bd01131c63..d88c752b449 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -282,10 +282,11 @@ pqsecure_open_client(PGconn *conn)
libpq_gettext("could not establish SSL connection: %s\n"),
err);
SSLerrfree(err);
- close_SSL(conn);
#ifdef ENABLE_THREAD_SAFETY
pthread_mutex_unlock(&ssl_config_mutex);
#endif
+ close_SSL(conn);
+
return PGRES_POLLING_FAILED;
}
#ifdef ENABLE_THREAD_SAFETY
@@ -1537,15 +1538,23 @@ open_client_SSL(PGconn *conn)
static void
close_SSL(PGconn *conn)
{
+ bool destroy_needed = false;
+
if (conn->ssl)
{
DECLARE_SIGPIPE_INFO(spinfo);
+ /*
+ * 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;
+
DISABLE_SIGPIPE(conn, spinfo, (void) 0);
SSL_shutdown(conn->ssl);
SSL_free(conn->ssl);
conn->ssl = NULL;
- pqsecure_destroy();
/* We have to assume we got EPIPE */
REMEMBER_EPIPE(spinfo, true);
RESTORE_SIGPIPE(conn, spinfo);
@@ -1565,6 +1574,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();
}
/*