v1-0001-Add-exit-check-for-libpq.so-for-meson-build.patch
text/x-patch
Filename: v1-0001-Add-exit-check-for-libpq.so-for-meson-build.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1-0001
Subject: Add exit() check for libpq.so for meson build
| File | + | − |
|---|---|---|
| src/interfaces/libpq/libpq-exit-check | 71 | 0 |
| src/interfaces/libpq/Makefile | 1 | 3 |
| src/interfaces/libpq/meson.build | 27 | 0 |
From 63a503dc5a3963b0e45e3634495563e52181bf23 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Wed, 19 Nov 2025 12:08:08 +0300
Subject: [PATCH v1] Add exit() check for libpq.so for meson build
---
src/interfaces/libpq/Makefile | 4 +-
src/interfaces/libpq/libpq-exit-check | 71 +++++++++++++++++++++++++++
src/interfaces/libpq/meson.build | 27 ++++++++++
3 files changed, 99 insertions(+), 3 deletions(-)
create mode 100755 src/interfaces/libpq/libpq-exit-check
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index da6650066d4..6b2d1769a07 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -144,9 +144,7 @@ $(stlib): $(OBJS_STATIC)
libpq-refs-stamp: $(shlib)
ifneq ($(enable_coverage), yes)
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
+ $(PERL) libpq-exit-check --input_file $<
endif
endif
touch $@
diff --git a/src/interfaces/libpq/libpq-exit-check b/src/interfaces/libpq/libpq-exit-check
new file mode 100755
index 00000000000..84fa2a7fbe0
--- /dev/null
+++ b/src/interfaces/libpq/libpq-exit-check
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings FATAL => 'all';
+
+use Getopt::Long;
+
+my $input_file;
+my $stamp_file;
+my @problematic_lines;
+
+GetOptions(
+ 'input_file:s' => \$input_file,
+ 'stamp_file:s' => \$stamp_file) or die "$0: wrong arguments";
+
+die "$0: --input_file must be specified\n" unless defined $input_file;
+
+open my $fh, '-|', "nm -A -u $input_file 2>/dev/null"
+ or die "Cannot run nm: $!";
+
+while (<$fh>)
+{
+ next if /__cxa_atexit/;
+ next if /__tsan_func_exit/;
+ next if /pthread_exit/;
+
+ if (/exit/)
+ {
+ push @problematic_lines, $_;
+ }
+}
+
+if (@problematic_lines)
+{
+ remove_stamp_file();
+
+ print "libpq must not be calling any function which invokes exit\n";
+ print "Problematic symbol references:\n";
+ print @problematic_lines;
+
+ exit 1;
+}
+else
+{
+ # All checks are passed, we can create a stamp file meson build now
+ if ($stamp_file)
+ {
+ create_stamp_file();
+ }
+
+ exit 0;
+}
+
+sub create_stamp_file
+{
+ # Avoid touching existing stamp file to prevent unnecessary rebuilds
+ if (!(-f $stamp_file))
+ {
+ open my $fh, '>', $stamp_file
+ or die "can't open $stamp_file: $!";
+ close $fh;
+ }
+}
+
+sub remove_stamp_file
+{
+ if ($stamp_file)
+ {
+ unlink $stamp_file;
+ }
+}
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index a74e885b169..978fff192ea 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -80,6 +80,33 @@ libpq_so = shared_library('libpq',
kwargs: default_lib_args,
)
+# 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.
+if find_program('nm', required: false, native: true).found() and portname != 'solaris' and not get_option('b_coverage')
+ custom_target(
+ 'libpq-exit-check',
+ input: libpq_so,
+ output: 'libpq-refs-stamp',
+ command: [
+ perl,
+ files('libpq-exit-check'),
+ '--input_file', '@INPUT@',
+ '--stamp_file', '@OUTPUT@'
+ ],
+ build_by_default: true,
+ )
+endif
+
libpq = declare_dependency(
link_with: [libpq_so],
include_directories: [include_directories('.')]
--
2.51.0