Static libpq and ecpglib clash with PThreads4W on Windows - Mailing list pgsql-bugs

From expl0it3r@my-gate.net
Subject Static libpq and ecpglib clash with PThreads4W on Windows
Date
Msg-id a004d8e3d6d95a560d402afeada99510@my-gate.net
Whole thread
List pgsql-bugs
Hi,

Linking the static libpq on Windows into an application that also uses a 
"real" pthreads library like PThreads4W fails with duplicate symbols:

   pthreadVC3d.lib(pthread.o) : error LNK2005: pthread_self already 
defined in pq.lib(pthread-win32.c.obj)
   pthreadVC3d.lib(pthread.o) : error LNK2005: pthread_mutex_init already 
defined in pq.lib(pthread-win32.c.obj)
   ...

libpq and ecpglib each bring a small pthread emulation on Windows 
(src/port/pthread-win32.h with src/interfaces/libpq/pthread-win32.c, and 
ecpg-pthread-win32.h with the definitions in ecpglib/misc.c), and the 
functions are named exactly like the official pthread ones. The static 
PThreads4W library is a single object file, so there's no way around it 
on the application side.

Depending on the link order, the two emulations also run into each 
other. On master, the following program fails to link against the static 
libecpg.a, libpq.a and PThreads4W:

   #include <stdio.h>
   #include <pthread.h>
   #include <libpq-fe.h>

   extern void *ECPGget_sqlca(void);

   int main(void)
   {
       PGconn *conn = PQconnectdb("host=localhost port=1 
connect_timeout=1");
       printf("%p %p\n", ECPGget_sqlca(), (void *) pthread_self().p);
       PQfinish(conn);
       return 0;
   }

   libpq.a(pthread-win32.c.obj) : error LNK2005: pthread_mutex_init 
already defined in libecpg.a(misc.c.obj)
   libpq.a(pthread-win32.c.obj) : error LNK2005: pthread_mutex_lock 
already defined in libecpg.a(misc.c.obj)
   libpq.a(pthread-win32.c.obj) : error LNK2005: pthread_mutex_unlock 
already defined in libecpg.a(misc.c.obj)

I ran into this through vcpkg, where pdal on the static Windows triplets 
pulls in libpq together with mbedtls built with pthreads. I've patched 
the vcpkg version, so the static Windows triplets no longer fail on CI 
[1].

The attached patch renames the functions with macros in the two 
emulation headers to pq_pthread_* and ecpg_pthread_*. The headers are 
included by the definitions and by every caller, and none of the 
functions are in exports.txt, so the call sites and the DLL ABI stay the 
same. The "Cleaning up threading code" thread [2] discussed essentially 
the same fix for the emulations, but it seems that it hasn't been 
implemented yet.

Tested with MSVC 2026 and meson on Windows: a full build, the ecpg suite 
(66 subtests including the thread tests), and the program above linking 
and running against the static libpq, ecpglib and PThreads4W, which 
fails on master.

[1] https://github.com/microsoft/vcpkg/pull/54377
[2] 
https://postgr.es/m/CA+hUKG+XpCcqoNe3-3oUzuGUeRoxAKqGnEAedvOhotsNCxuS+Q@mail.gmail.com

Kind regards,
Lukas
Attachment

pgsql-bugs by date:

Previous
From: Chinmay Kanchi
Date:
Subject: GIN (JSONPath) checks equality only on the first node of each operand
Next
From: Tom Lane
Date:
Subject: Re: GIN (JSONPath) checks equality only on the first node of each operand