libpq: Add PQgetThreadLock() to mirror PQregisterThreadLock()

Allow libpq clients to retrieve the current pg_g_threadlock pointer with
PQgetThreadLock(). Single-threaded applications could already do this in
a convoluted way:

    pgthreadlock_t tlock;

    tlock = PQregisterThreadLock(NULL);
    PQregisterThreadLock(tlock);    /* re-register the callback */

    /* use tlock */

But a generic library can't do that without potentially breaking
concurrent libpq connections.

The motivation for doing this now is the libpq-oauth plugin, which
currently relies on direct injection of pg_g_threadlock, and should
ideally not.

Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/CAOYmi%2BmEU_q9sr1PMmE-4rLwFN%3DOjyndDwFZvpsMU3RNJLrM9g%40mail.gmail.com
Discussion: https://postgr.es/m/CAOYmi%2B%3DMHD%2BWKD4rsTn0v8220mYfyLGhEc5EfhmtqrAb7SmC5g%40mail.gmail.com
This commit is contained in:
Jacob Champion 2026-03-05 10:04:48 -08:00
parent f8c0b91a60
commit b8d7685835
4 changed files with 21 additions and 3 deletions

View file

@ -10635,7 +10635,11 @@ int PQisthreadsafe();
Kerberos calls because Kerberos functions are not thread-safe. See
function <function>PQregisterThreadLock</function> in the
<application>libpq</application> source code for a way to do cooperative
locking between <application>libpq</application> and your application.
locking between <application>libpq</application> and your application. (Note
that it is only safe to call <function>PQregisterThreadLock</function> when
there are no open connections.) Clients may retrieve the current locking
callback with <function>PQgetThreadLock</function>; if no custom callback
has been registered, a default is used.
</para>
<para>

View file

@ -210,3 +210,4 @@ PQgetAuthDataHook 207
PQdefaultAuthDataHook 208
PQfullProtocolVersion 209
appendPQExpBufferVA 210
PQgetThreadLock 211

View file

@ -8414,3 +8414,10 @@ PQregisterThreadLock(pgthreadlock_t newhandler)
return prev;
}
pgthreadlock_t
PQgetThreadLock(void)
{
Assert(pg_g_threadlock);
return pg_g_threadlock;
}

View file

@ -63,6 +63,10 @@ extern "C"
/* Indicates presence of the PQAUTHDATA_PROMPT_OAUTH_DEVICE authdata hook */
#define LIBPQ_HAS_PROMPT_OAUTH_DEVICE 1
/* Features added in PostgreSQL v19: */
/* Indicates presence of PQgetThreadLock */
#define LIBPQ_HAS_GET_THREAD_LOCK 1
/*
* Option flags for PQcopyResult
*/
@ -462,12 +466,14 @@ extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
* Used to set callback that prevents concurrent access to
* non-thread safe functions that libpq needs.
* The default implementation uses a libpq internal mutex.
* Only required for multithreaded apps that use kerberos
* both within their app and for postgresql connections.
* Only required for multithreaded apps that use Kerberos or
* older (non-threadsafe) versions of Curl both within their
* app and for postgresql connections.
*/
typedef void (*pgthreadlock_t) (int acquire);
extern pgthreadlock_t PQregisterThreadLock(pgthreadlock_t newhandler);
extern pgthreadlock_t PQgetThreadLock(void);
/* === in fe-trace.c === */
extern void PQtrace(PGconn *conn, FILE *debug_port);