BUG #19095: Test if function exit() is used fail when linked static

Started by PG Bug reporting form4 months ago34 messages
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 19095
Logged by: Torsten Rupp
Email address: torsten.rupp@gmx.net
PostgreSQL version: 15.14
Operating system: Linux
Description:

Note: occur from version 15.14 or newer.

In src/interfaces/libpq/Makefile is a test if the function "exit()" (or in
general: a function exists with the name part "exit") is used:

libpq-refs-stamp: $(shlib)
ifneq ($(enable_coverage), yes)
ifeq (,$(filter aix solaris,$(PORTNAME)))
@if nm -A -u $< 2>/dev/null | grep -v __cxa_atexit | grep exit; then
\
echo 'libpq must not be calling any function which invokes
exit'; exit 1; \
fi
endif
endif

This test fail if libpq is linked static to an application when e. g.
libcrypto is also linked static into libpq which add indirectly a call to
"pthread_exit()".

Possible fix: exclude pthread_exit(), too (like __cxa_atexit), e.g.:

libpq-refs-stamp: $(shlib)
ifneq ($(enable_coverage), yes)
ifeq (,$(filter aix solaris,$(PORTNAME)))
@if nm -A -u $< 2>/dev/null | grep -v __cxa_atexit | grep -v
pthread_exit | grep exit; then \
echo 'libpq must not be calling any function which invokes
exit'; exit 1; \
fi
endif
endif

#2Michael Paquier
michael@paquier.xyz
In reply to: PG Bug reporting form (#1)
Re: BUG #19095: Test if function exit() is used fail when linked static

On Mon, Oct 27, 2025 at 07:56:38AM +0000, PG Bug reporting form wrote:

This test fail if libpq is linked static to an application when e. g.
libcrypto is also linked static into libpq which add indirectly a call to
"pthread_exit()".

Possible fix: exclude pthread_exit(), too (like __cxa_atexit), e.g.:

Previous discussions around this check:
- 936f56988741, with:
/messages/by-id/CAEhC_BmNGKgj2wKArH2EAU11BsaHYgLnrRFJGRm5Vs8WJzyiQA@mail.gmail.com
- dc227eb82ea8, with:
/messages/by-id/3128896.1624742969@sss.pgh.pa.us

We have usually used the buildfarm to decide how much restriction we
should put into this one, for good historical reasons because we
should never exit() directly from libpq, like this one:
/messages/by-id/20210703001639.GB2374652@rfd.leadboat.com

Treating pthread_exit() as an exception sounds like it may be a good
thing anyway: we don't rely on it in the code core.

Now I am not completely sure how much we should care about considering
that any of that as something we need to tweak in the core code. The
use of static libraries are usually discouraged, because it makes the
handling of package dependencies more complicated if some
sub-libraries need to be upgraded following a CVE-class issue, and
here you are pointing at what looks like a custom static library build
of libcrypto on Linux.

Opinions from others are welcome, mine counts like -0.5.
--
Michael

#3Torsten Rupp
torsten.rupp@gmx.net
In reply to: PG Bug reporting form (#1)
Re: BUG #19095: Test if function exit() is used fail when linked static

Dear developers,

I opened this request for a behavior concerning functions with the name
part "exit":

Bug reference: 19095
Logged by: Torsten Rupp
Email address: torsten.rupp@gmx.net
PostgreSQL version: 15.14
Operating system: Linux
Description:

Note: occur from version 15.14 or newer.

In src/interfaces/libpq/Makefile is a test if the function "exit()" (or in
general: a function exists with the name part "exit") is used:

libpq-refs-stamp: $(shlib)
ifneq ($(enable_coverage), yes)
ifeq (,$(filter aix solaris,$(PORTNAME)))
@if nm -A -u $< 2>/dev/null | grep -v __cxa_atexit | grep exit; then
\
echo 'libpq must not be calling any function which invokes
exit'; exit 1; \
fi
endif
endif

This test fail if libpq is linked static to an application when e. g.
libcrypto is also linked static into libpq which add indirectly a call to
"pthread_exit()".

Possible fix: exclude pthread_exit(), too (like __cxa_atexit), e.g.:

libpq-refs-stamp: $(shlib)
ifneq ($(enable_coverage), yes)
ifeq (,$(filter aix solaris,$(PORTNAME)))
@if nm -A -u $< 2>/dev/null | grep -v __cxa_atexit | grep -v
pthread_exit | grep exit; then \
echo 'libpq must not be calling any function which invokes
exit'; exit 1; \
fi
endif
endif

BTW: if you wonder about static linkage: I'm aware of the disadvantages,
but I use static linkage for a backup tool which should run e. g. in any
live Linux from a USB medium, thus it should have as less dependencies
to shared libraries as possible. A non-static version of the tool is
also available. The issue does not occur with shared libraries, because
then no function with the name part "exit" is linked into libpq.

Thank you for your attention.

Best regards, Torsten Rupp

#4BharatDB
bharatdbpg@gmail.com
In reply to: PG Bug reporting form (#1)
Re: BUG #19095: Test if function exit() is used fail when linked static

Hello Hackers,

While reproducing a static linking issue between libpq and libcrypto.a,
I observed that the Makefile's symbol check incorrectly reports missing
exit() symbols because 'grep exit' also matches 'atexit' and
'OPENSSL_atexit', etc.

As discussed in the thread by Michael Paquier
(/messages/by-id/aQA1obboZFjqjaBI@paquier.xyz),
it seems a related fix was committed earlier. However, I was able to
reproduce this issue again using PostgreSQL 18 (latest release).

Steps to reproduce:
nm -A -u ./src/interfaces/libpq/libpq.a
/usr/lib/x86_64-linux-gnu/libcrypto.a 2>/dev/null | grep -v __cxa_atexit |
grep exit

Output:
/usr/lib/x86_64-linux-gnu/libcrypto.a:libcrypto-lib-init.o:
U atexit
/usr/lib/x86_64-linux-gnu/libcrypto.a:libdefault-lib-rand_unix.o:
U OPENSSL_atexit

This falsely triggers an undefined exit() error.
[1]Changing the grep pattern to match the exact symbol ('grep -x exit')
prevents
such false positives.

[2]: Alternatively, excluding pthread_exit() (similar to

__cxa_atexit) would also avoid the issue.

But [1] will handle all the false positives instead of just pthread_exit

.LGTM

Expected (after fix):

no output — no false positives.

Patch attached.I would love to hear any suggestions from the committers.

Thanks in advance

Best regards,
Vasuki M

BharatDB,

Show quoted text

CDAC Chennai.

Attachments:

0001-Fix-prevent-false-exit-match-in-libpq-static-link-ch.patchtext/x-patch; charset=US-ASCII; name=0001-Fix-prevent-false-exit-match-in-libpq-static-link-ch.patchDownload+1-2
#5BharatDB
bharatdbpg@gmail.com
In reply to: BharatDB (#4)
Fwd: BUG #19095: Test if function exit() is used fail when linked static

---------- Forwarded message ---------
From: BharatDB <bharatdbpg@gmail.com>
Date: Wed, Nov 12, 2025 at 11:23 AM
Subject: Re: BUG #19095: Test if function exit() is used fail when linked
static
To: <torsten.rupp@gmx.net>, <pgsql-bugs@lists.postgresql.org>, <
michael@paquier.xyz>
Cc: VASUKI M <vasukim1992002@gmail.com>

Hello Hackers,

While reproducing a static linking issue between libpq and libcrypto.a,
I observed that the Makefile's symbol check incorrectly reports missing
exit() symbols because 'grep exit' also matches 'atexit' and
'OPENSSL_atexit', etc.

As discussed in the thread by Michael Paquier
(/messages/by-id/aQA1obboZFjqjaBI@paquier.xyz),
it seems a related fix was committed earlier. However, I was able to
reproduce this issue again using PostgreSQL 18 (latest release).

Steps to reproduce:
nm -A -u ./src/interfaces/libpq/libpq.a
/usr/lib/x86_64-linux-gnu/libcrypto.a 2>/dev/null | grep -v __cxa_atexit |
grep exit

Output:
/usr/lib/x86_64-linux-gnu/libcrypto.a:libcrypto-lib-init.o:
U atexit
/usr/lib/x86_64-linux-gnu/libcrypto.a:libdefault-lib-rand_unix.o:
U OPENSSL_atexit

This falsely triggers an undefined exit() error.
[1]Changing the grep pattern to match the exact symbol ('grep -x exit')
prevents
such false positives.

[2]: Alternatively, excluding pthread_exit() (similar to

__cxa_atexit) would also avoid the issue.

But [1] will handle all the false positives instead of just pthread_exit

.LGTM

Expected (after fix):

no output — no false positives.

Patch attached.I would love to hear any suggestions from the committers.

Thanks in advance

Best regards,
Vasuki M

BharatDB,

Show quoted text

CDAC Chennai.

Attachments:

0001-Fix-prevent-false-exit-match-in-libpq-static-link-ch.patchapplication/x-patch; name=0001-Fix-prevent-false-exit-match-in-libpq-static-link-ch.patchDownload+1-2
#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: BharatDB (#4)
Re: BUG #19095: Test if function exit() is used fail when linked static

BharatDB <bharatdbpg@gmail.com> writes:

[1]Changing the grep pattern to match the exact symbol ('grep -x exit')
prevents such false positives.

We might as well remove the test entirely as do that; it would
fail to detect "_exit" for example.

Additionally, I don't have a lot of faith in "grep -x" being
universally portable. POSIX 2018 does specify that switch, but
it mentions that it is "historically available only with fgrep".

Personally I'm okay with whitelisting pthread_exit() as
Torsten suggested.

BTW, it looks like libpq's meson.build is missing this check.

regards, tom lane

#7Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#6)
Re: BUG #19095: Test if function exit() is used fail when linked static

On 12 Nov 2025, at 07:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Personally I'm okay with whitelisting pthread_exit() as
Torsten suggested.

+1, we already have a few whitelisted entries and pthread_exit seems perfectly
reasonable to add to that list.

--
Daniel Gustafsson

#8Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#7)
Re: BUG #19095: Test if function exit() is used fail when linked static

On Wed, Nov 12, 2025 at 09:13:09AM +0100, Daniel Gustafsson wrote:

On 12 Nov 2025, at 07:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Personally I'm okay with whitelisting pthread_exit() as
Torsten suggested.

+1, we already have a few whitelisted entries and pthread_exit seems perfectly
reasonable to add to that list.

WFM.
--
Michael

#9Daniel Gustafsson
daniel@yesql.se
In reply to: Michael Paquier (#8)
Re: BUG #19095: Test if function exit() is used fail when linked static

On 12 Nov 2025, at 09:15, Michael Paquier <michael@paquier.xyz> wrote:

On Wed, Nov 12, 2025 at 09:13:09AM +0100, Daniel Gustafsson wrote:

On 12 Nov 2025, at 07:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Personally I'm okay with whitelisting pthread_exit() as
Torsten suggested.

+1, we already have a few whitelisted entries and pthread_exit seems perfectly
reasonable to add to that list.

WFM.

The attached trivial diff adds this to the whitelist clause in the Makefile. I
experimented with adding this to Meson, and while it's trivial enough to do the
run_command with libpq_so.full_path, it's less clear to me exactly where in the
build it should be added. I've pinged my colleague Bilal who is much better at
Meson than me to collaborate on that as a separate fix.

--
Daniel Gustafsson

Attachments:

pthread_exit_whitelist.diffapplication/octet-stream; name=pthread_exit_whitelist.diff; x-unix-mode=0644Download+1-1
#10Andres Freund
andres@anarazel.de
In reply to: Daniel Gustafsson (#9)
Re: BUG #19095: Test if function exit() is used fail when linked static

Hi,
On 2025-11-14 13:11:15 +0100, Daniel Gustafsson wrote:

On 12 Nov 2025, at 09:15, Michael Paquier <michael@paquier.xyz> wrote:

On Wed, Nov 12, 2025 at 09:13:09AM +0100, Daniel Gustafsson wrote:

On 12 Nov 2025, at 07:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Personally I'm okay with whitelisting pthread_exit() as
Torsten suggested.

+1, we already have a few whitelisted entries and pthread_exit seems perfectly
reasonable to add to that list.

WFM.

The attached trivial diff adds this to the whitelist clause in the Makefile. I
experimented with adding this to Meson, and while it's trivial enough to do the
run_command with libpq_so.full_path, it's less clear to me exactly where in the
build it should be added. I've pinged my colleague Bilal who is much better at
Meson than me to collaborate on that as a separate fix.

For meson we'll have to filter where we test this more strictly - it'll
e.g. not work on windows, because there's no nm, perhaps no grep, etc.

But more generally: If we allow pthread_exit(), what's the point of this test?
That's one of the functions we better avoid calling, no?

ISTM that if we do want to continue having this test, the issue is that we're
testing the shared library - which will have already linked against static
libraries like the sanitizer ones or in this case libcrypto. What we ought to
do is to test the .o files constituting libpq.so, rather than the already
linked .so. That way we will find our own calls to exit etc, but not ones in
static libraries.

Greetings,

Andres Freund

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#10)
Re: BUG #19095: Test if function exit() is used fail when linked static

Andres Freund <andres@anarazel.de> writes:

But more generally: If we allow pthread_exit(), what's the point of this test?
That's one of the functions we better avoid calling, no?

ATM it's not something we'd be tempted to call, but I take your point.

ISTM that if we do want to continue having this test, the issue is that we're
testing the shared library - which will have already linked against static
libraries like the sanitizer ones or in this case libcrypto. What we ought to
do is to test the .o files constituting libpq.so, rather than the already
linked .so. That way we will find our own calls to exit etc, but not ones in
static libraries.

My recollection is that that doesn't help as much as you'd think.
__tsan_func_exit, for one, can get injected into our own .o files
if we build with appropriate sanitizers enabled.

regards, tom lane

#12BharatDB
bharatdbpg@gmail.com
In reply to: Andres Freund (#10)
Re: BUG #19095: Test if function exit() is used fail when linked static

Hi Andres and hackers,
I came up with the solution
— short follow-up with what I changed and how the Meson check actually runs.

Summary of what I did
- Added a Meson custom_target in src/interfaces/libpq/meson.build that
scans libpq's object files for direct exit() references.
- Added pthread_exit to the Makefile whitelist (the Makefile test
already existed; this just updates the whitelist).
-Added the custom target in the top level meson.build

Where the Meson check lives and when it runs
- I put the custom_target in src/interfaces/libpq/meson.build,
immediately after the libpq shared/static library targets are
defined and after the declare_dependency for libpq. That is the
correct location in the libpq build file.
- The custom_target declares `depends: [libpq_st, libpq_so]`. This
is important: it tells Meson to build those targets first so the
.o files are present in the build directory before the check runs.
The check itself does not scan libpq_st or libpq_so; it scans
files in build/src/interfaces/libpq/*.o.
- The command uses `find <builddir>/src/interfaces/libpq -name '*.o'`
and runs `nm -u` on each .o, piping through `grep -v` for the
whitelisted names and finally checking for exit.
- The check is skipped for:
* cross-builds
* when coverage (b_coverage) is enabled
* on Windows (no nm/grep in the same form there) as Andrew questioned

Why pthread_exit is whitelisted
- pthread_exit can legitimately appear in a few build/runtime
configurations (thread runtimes or link-time glue), and the
Makefile test was updated to whitelist it. The Meson check has the
same whitelist so both build systems behave the same.
- Whitelisting pthread_exit doesn't remove the value of the test:
it only avoids false positives for legitimate thread shutdown code.
We still catch direct exit()/ _exit()/abort()-style calls as tom said.

How to reproduce locally
- From repo root:
rm -rf build
meson setup build
cd build
ninja
The custom_target runs as part of the normal build and will fail
the build if any .o contains an un-whitelisted exit() reference.

On Fri, Nov 14, 2025 at 7:31 PM Andres Freund <andres@anarazel.de> wrote:

But more generally: If we allow pthread_exit(), what's the point of this

test?
That's one of the functions we better avoid calling, no?

I agree it's worth questioning which functions we allow. The
current choice (whitelist pthread_exit) mirrors the Makefile
behavior, avoids false positives, and keeps the test focused on
direct process-termination calls authored in our code. If the
community prefers a stricter policy so we can adjust the whitelist.

ISTM that if we do want to continue having this test, the issue is that
we're
testing the shared library - which will have already linked against static
libraries like the sanitizer ones or in this case libcrypto. What we ought
to
do is to test the .o files constituting libpq.so, rather than the already
linked .so. That way we will find our own calls to exit etc, but not ones
in
static libraries.

TBH After so many test runs I have finalized
Why scan .o files (not the final .so)?
- A shared library is usually linked with other static libraries
(libcrypto, sanitizer runtimes). If we scan the final .so we'll
see references that originate in those static libraries and produce
false positives.
- If we scan the .o files that make up libpq, we only inspect our
own compilation units and will catch only exit() calls introduced
by our code.

HTH! I attached the patch and also added the meson test output before
/after of any file containing an 'exit' explicitly; it fails the
build[ninja].

Regards,
Vasuki M
BharatDB[CDAC chennai]

Attachments:

0001-libpq-exit-check-function-for-meson-and-Makefile.patchtext/x-patch; charset=UTF-8; name=0001-libpq-exit-check-function-for-meson-and-Makefile.patchDownload+37-42
Screenshot from 2025-11-18 17-57-16.pngimage/png; name="Screenshot from 2025-11-18 17-57-16.png"Download
Screenshot from 2025-11-18 17-59-06.pngimage/png; name="Screenshot from 2025-11-18 17-59-06.png"Download
#13BharatDB
bharatdbpg@gmail.com
In reply to: BharatDB (#12)
Re: BUG #19095: Test if function exit() is used fail when linked static

Sorry,for the wrong patch this is the correct one.kindly find the attached
patch for testing
I would love to hear the feedback from you committers.

regards,
Vasuki M
BharatDB,C-DAC Chennai.

On Wed, Nov 19, 2025 at 2:38 PM BharatDB <bharatdbpg@gmail.com> wrote:

Show quoted text

Hi Andres and hackers,
I came up with the solution
— short follow-up with what I changed and how the Meson check actually
runs.

Summary of what I did
- Added a Meson custom_target in src/interfaces/libpq/meson.build that
scans libpq's object files for direct exit() references.
- Added pthread_exit to the Makefile whitelist (the Makefile test
already existed; this just updates the whitelist).
-Added the custom target in the top level meson.build

Where the Meson check lives and when it runs
- I put the custom_target in src/interfaces/libpq/meson.build,
immediately after the libpq shared/static library targets are
defined and after the declare_dependency for libpq. That is the
correct location in the libpq build file.
- The custom_target declares `depends: [libpq_st, libpq_so]`. This
is important: it tells Meson to build those targets first so the
.o files are present in the build directory before the check runs.
The check itself does not scan libpq_st or libpq_so; it scans
files in build/src/interfaces/libpq/*.o.
- The command uses `find <builddir>/src/interfaces/libpq -name '*.o'`
and runs `nm -u` on each .o, piping through `grep -v` for the
whitelisted names and finally checking for exit.
- The check is skipped for:
* cross-builds
* when coverage (b_coverage) is enabled
* on Windows (no nm/grep in the same form there) as Andrew questioned

Why pthread_exit is whitelisted
- pthread_exit can legitimately appear in a few build/runtime
configurations (thread runtimes or link-time glue), and the
Makefile test was updated to whitelist it. The Meson check has the
same whitelist so both build systems behave the same.
- Whitelisting pthread_exit doesn't remove the value of the test:
it only avoids false positives for legitimate thread shutdown code.
We still catch direct exit()/ _exit()/abort()-style calls as tom said.

How to reproduce locally
- From repo root:
rm -rf build
meson setup build
cd build
ninja
The custom_target runs as part of the normal build and will fail
the build if any .o contains an un-whitelisted exit() reference.

On Fri, Nov 14, 2025 at 7:31 PM Andres Freund <andres@anarazel.de> wrote:

But more generally: If we allow pthread_exit(), what's the point of this

test?
That's one of the functions we better avoid calling, no?

I agree it's worth questioning which functions we allow. The
current choice (whitelist pthread_exit) mirrors the Makefile
behavior, avoids false positives, and keeps the test focused on
direct process-termination calls authored in our code. If the
community prefers a stricter policy so we can adjust the whitelist.

ISTM that if we do want to continue having this test, the issue is that
we're
testing the shared library - which will have already linked against static
libraries like the sanitizer ones or in this case libcrypto. What we
ought to
do is to test the .o files constituting libpq.so, rather than the already
linked .so. That way we will find our own calls to exit etc, but not ones
in
static libraries.

TBH After so many test runs I have finalized
Why scan .o files (not the final .so)?
- A shared library is usually linked with other static libraries
(libcrypto, sanitizer runtimes). If we scan the final .so we'll
see references that originate in those static libraries and produce
false positives.
- If we scan the .o files that make up libpq, we only inspect our
own compilation units and will catch only exit() calls introduced
by our code.

HTH! I attached the patch and also added the meson test output before
/after of any file containing an 'exit' explicitly; it fails the
build[ninja].

Regards,
Vasuki M
BharatDB[CDAC chennai]

Attachments:

0001-libpq-Add-exit-function-check-for-Meson-build-and-wh.patchtext/x-patch; charset=UTF-8; name=0001-libpq-Add-exit-function-check-for-Meson-build-and-wh.patchDownload+34-3
#14Nazir Bilal Yavuz
byavuz81@gmail.com
In reply to: Daniel Gustafsson (#9)
Re: BUG #19095: Test if function exit() is used fail when linked static

Hi,

On Fri, 14 Nov 2025 at 15:11, Daniel Gustafsson <daniel@yesql.se> wrote:

On 12 Nov 2025, at 09:15, Michael Paquier <michael@paquier.xyz> wrote:

On Wed, Nov 12, 2025 at 09:13:09AM +0100, Daniel Gustafsson wrote:

On 12 Nov 2025, at 07:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Personally I'm okay with whitelisting pthread_exit() as
Torsten suggested.

+1, we already have a few whitelisted entries and pthread_exit seems perfectly
reasonable to add to that list.

WFM.

The attached trivial diff adds this to the whitelist clause in the Makefile. I
experimented with adding this to Meson, and while it's trivial enough to do the
run_command with libpq_so.full_path, it's less clear to me exactly where in the
build it should be added. I've pinged my colleague Bilal who is much better at
Meson than me to collaborate on that as a separate fix.

Sorry for the late reply. I replaced the Makefile portion with the
Perl script, so that it can be used for both meson and autoconf build
systems. The script takes two arguments

- input_file -> path of library file.
- stamp_file -> to create a stamp file for the meson build, so that
meson does not run while the library file is not changed. Autoconf
build does not use this option.

--
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

v1-0001-Add-exit-check-for-libpq.so-for-meson-build.patchtext/x-patch; charset=US-ASCII; name=v1-0001-Add-exit-check-for-libpq.so-for-meson-build.patchDownload+99-4
#15Nazir Bilal Yavuz
byavuz81@gmail.com
In reply to: Nazir Bilal Yavuz (#14)
Re: BUG #19095: Test if function exit() is used fail when linked static

Hi,

On Wed, 19 Nov 2025 at 16:17, Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:

Sorry for the late reply. I replaced the Makefile portion with the
Perl script, so that it can be used for both meson and autoconf build
systems.

Apparently we do not need to remove the stamp-file in the perl script,
meson already handles that internally. v2 is attached.

--
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

v2-0001-Add-exit-check-for-libpq.so-for-meson-build.patchtext/x-patch; charset=US-ASCII; name=v2-0001-Add-exit-check-for-libpq.so-for-meson-build.patchDownload+89-4
#16Michael Paquier
michael@paquier.xyz
In reply to: Nazir Bilal Yavuz (#15)
Re: BUG #19095: Test if function exit() is used fail when linked static

On Mon, Nov 24, 2025 at 02:04:01PM +0300, Nazir Bilal Yavuz wrote:

Apparently we do not need to remove the stamp-file in the perl script,
meson already handles that internally. v2 is attached.

Good idea to embed that in a perl script!

+# Check for functions that libpq must not call, currently just exit().
+# (Ideally we'd reject abort() too, but there are various scenarios where
+# build toolchains insert abort() calls, e.g. to implement assert().)
+# If nm doesn't exist or doesn't work on shlibs, this test will do nothing,
+# which is fine.  The exclusion of __cxa_atexit is necessary on OpenBSD,
+# which seems to insert references to that even in pure C code. Excluding
+# __tsan_func_exit is necessary when using ThreadSanitizer data race detector
+# which use this function for instrumentation of function exit.
+# Skip the test when profiling, as gcc may insert exit() calls for that.
+# Also skip the test on platforms where libpq infrastructure may be provided
+# by statically-linked libraries, as we can't expect them to honor this
+# coding rule.

Including a reference to "nm" in this comment for meson is definitely
fine, because it is used as a pre-check in this code with
find_program. However, shouldn't we document the platform-specific
exclusions in the perl script itself? As of the patch, the
explanation is a copy-paste of src/interfaces/libpq/Makefile. I think
that we'd better group everything together, rather than have the same
contents explained in two places. Perhaps I would add an extra
comment in meson.build and the Makefile to document that all the
platform-relevant details are in the perl script itself.

I would be also tempted to move the solaris check inside the perl
script rather than have it duplicated across meson and make, then do
something based on $Config{osname} instead.
--
Michael

#17VASUKI M
vasukim1992002@gmail.com
In reply to: Michael Paquier (#16)
Re: BUG #19095: Test if function exit() is used fail when linked static

On Tue, 25 Nov 2025 at 03:14, Michael Paquier <michael@paquier.xyz> wrote:

Including a reference to "nm" in this comment for meson is definitely
fine, because it is used as a pre-check in this code with
find_program. However, shouldn't we document the platform-specific
exclusions in the perl script itself? As of the patch, the
explanation is a copy-paste of src/interfaces/libpq/Makefile. I think
that we'd better group everything together, rather than have the same
contents explained in two places. Perhaps I would add an extra
comment in meson.build and the Makefile to document that all the
platform-relevant details are in the perl script itself.

Thanks for this suggestion michael & Nazir for the code,i have made the

changes you said

Also added the check where it scans for nm in the environment if it is not
present then it gracefully skips the test.
V3 attached kindly check and review it.

I would be also tempted to move the solaris check inside the perl
script rather than have it duplicated across meson and make, then do
something based on $Config{osname} instead.

Done

Testing performed:
- Built with both autoconf+Makefile and Meson builds.
- Verified the script runs inside Meson via the custom_target and
confirmed with ninja -v.

grep -R "libpq-exit-check" build.ninja

build src/interfaces/libpq/libpq-refs-stamp: CUSTOM_COMMAND
src/interfaces/libpq/libpq.so.5.19 |
../src/interfaces/libpq/libpq-exit-check /usr/bin/perl
COMMAND = /usr/bin/perl ../src/interfaces/libpq/libpq-exit-check
--input_file src/interfaces/libpq/libpq.so.5.19 --stamp_file
src/interfaces/libpq/libpq-refs-stamp
description = Generating$ src/interfaces/libpq/libpq-exit-check$ with$ a$
custom$ command

- Injected a fake exit() reference into fe-connect.c and ensured the
build fails with the expected error message.
- Confirmed that removing nm causes the script to skip the check cleanly.
- Verified that Meson’s stamp file prevents re-running the check when
libpq.so has not changed.

Regards,
Vasuki M
CDAC-Chennai

Attachments:

v3-0001-libpq-exit-check.patchtext/x-patch; charset=UTF-8; name=v3-0001-libpq-exit-check.patchDownload+118-18
#18Nazir Bilal Yavuz
byavuz81@gmail.com
In reply to: VASUKI M (#17)
Re: BUG #19095: Test if function exit() is used fail when linked static

Hi,

On Tue, 25 Nov 2025 at 12:11, VASUKI M <vasukim1992002@gmail.com> wrote:

On Tue, 25 Nov 2025 at 03:14, Michael Paquier <michael@paquier.xyz> wrote:

Including a reference to "nm" in this comment for meson is definitely
fine, because it is used as a pre-check in this code with
find_program. However, shouldn't we document the platform-specific
exclusions in the perl script itself? As of the patch, the
explanation is a copy-paste of src/interfaces/libpq/Makefile. I think
that we'd better group everything together, rather than have the same
contents explained in two places. Perhaps I would add an extra
comment in meson.build and the Makefile to document that all the
platform-relevant details are in the perl script itself.

Thanks for this suggestion michael & Nazir for the code,i have made the changes you said

Also added the check where it scans for nm in the environment if it is not present then it gracefully skips the test.
V3 attached kindly check and review it.

Thank you for working on this!

diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index da66500..305361f 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
-ifeq (,$(filter solaris,$(PORTNAME)))
-    @if nm -A -u $< 2>/dev/null | grep -v -e __cxa_atexit -e
__tsan_func_exit | grep exit; then \
-        echo 'libpq must not be calling any function which invokes
exit'; exit 1; \
-    fi
+    # See libpq-exit-check for full platform rules and whitelisting.
+    $(PERL) libpq-exit-check --input_file $<
 endif
-endif
-    touch $@
+    touch $@

There are unnecessary indentation changes.

diff --git a/src/interfaces/libpq/libpq-exit-check
b/src/interfaces/libpq/libpq-exit-check
new file mode 100755
index 0000000..f500cef
--- /dev/null
+++ b/src/interfaces/libpq/libpq-exit-check

I would prefer more in-line comments instead of the comment at the top
but I think this is a preference.

diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index a74e885..1b32eed 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build

+if find_program('nm', required: false, native: true).found() and not
get_option('b_coverage')

I would delete the 'nm' check there, since we have the same check in
the PERL script. This makes the meson.build and the Makefile more
similar.

Also, I would change the comment at the Makefile and the meson.build
with the comment below, otherwise we lose information:

# Check for functions that libpq must not call, currently just exit().
# (Ideally we'd reject abort() too, but there are various scenarios where
# build toolchains insert abort() calls, e.g. to implement assert().)
# Skip the test when profiling, as gcc may insert exit() calls for that.

Nitpick: I suggest running pgperltidy [1]https://github.com/postgres/postgres/blob/master/src/tools/pgindent/pgperltidy on the libq-exit-check PERL file.

[1]: https://github.com/postgres/postgres/blob/master/src/tools/pgindent/pgperltidy

--
Regards,
Nazir Bilal Yavuz
Microsoft

#19Daniel Gustafsson
daniel@yesql.se
In reply to: VASUKI M (#17)
Re: BUG #19095: Test if function exit() is used fail when linked static

On 25 Nov 2025, at 10:11, VASUKI M <vasukim1992002@gmail.com> wrote:

Thanks for this suggestion michael & Nazir for the code,i have made the changes you said

Also added the check where it scans for nm in the environment if it is not present then it gracefully skips the test.

+if find_program('nm', required: false, native: true).found() and not get_option('b_coverage')
Sorry for being late to the party, but I wonder why we aren't adding this check
to the toplevel meson.build and configure.ac (via config/programs.m4) like how
we check for all others tools used by the build? Such checks should of course
not fail the configuration, merely record the presence or absence of the tool.
The path can then be exported to src/interfaces/libpq/{Makefile|meson.build} to
use.

+open my $fh, '-|', "$nm_path -A -u $input_file 2>/dev/null"
This filehandle is never closed.

+# ---- Skip entirely on Solaris ----
+if ($Config{osname} =~ /solaris/i) {
+    exit 0;
+}
This won't work on Windows either, which wasn't checked for in the Makefile
since make isn't used on Windows.

--
Daniel Gustafsson

#20Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#19)
Re: BUG #19095: Test if function exit() is used fail when linked static

On Tue, Nov 25, 2025 at 11:51:55AM +0100, Daniel Gustafsson wrote:

+if find_program('nm', required: false, native: true).found() and not get_option('b_coverage')
Sorry for being late to the party, but I wonder why we aren't adding this check
to the toplevel meson.build and configure.ac (via config/programs.m4) like how
we check for all others tools used by the build? Such checks should of course
not fail the configuration, merely record the presence or absence of the tool.
The path can then be exported to src/interfaces/libpq/{Makefile|meson.build} to
use.

+1 for this find_program() call grouped at the top of meson.build,
grouped with the others.
--
Michael
#21VASUKI M
vasukim1992002@gmail.com
In reply to: Michael Paquier (#20)
#22VASUKI M
vasukim1992002@gmail.com
In reply to: VASUKI M (#21)
#23Daniel Gustafsson
daniel@yesql.se
In reply to: VASUKI M (#22)
#24Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#23)
#25VASUKI M
vasukim1992002@gmail.com
In reply to: Michael Paquier (#24)
#26Michael Paquier
michael@paquier.xyz
In reply to: VASUKI M (#25)
#27VASUKI M
vasukim1992002@gmail.com
In reply to: Michael Paquier (#26)
#28Michael Paquier
michael@paquier.xyz
In reply to: VASUKI M (#27)
#29Peter Eisentraut
peter_e@gmx.net
In reply to: Michael Paquier (#28)
#30Michael Paquier
michael@paquier.xyz
In reply to: Peter Eisentraut (#29)
#31VASUKI M
vasukim1992002@gmail.com
In reply to: Michael Paquier (#30)
#32Nazir Bilal Yavuz
byavuz81@gmail.com
In reply to: VASUKI M (#31)
#33Michael Paquier
michael@paquier.xyz
In reply to: Nazir Bilal Yavuz (#32)
#34Michael Paquier
michael@paquier.xyz
In reply to: Michael Paquier (#33)