1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#!/usr/bin/perl
#
# src/interfaces/libpq/libpq_check.pl
#
# Copyright (c) 2025, PostgreSQL Global Development Group
#
# Check the state of a libpq library. Currently, this script checks that
# exit() is not called, because client libraries must not terminate the
# host application.
#
# This script is called by both Makefile and Meson.
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
use Config;
my $nm_path;
my $input_file;
my $stamp_file;
my @problematic_lines;
Getopt::Long::GetOptions(
'nm:s' => \$nm_path,
'input_file:s' => \$input_file,
'stamp_file:s' => \$stamp_file) or die "$0: wrong arguments\n";
die "$0: --input_file must be specified\n" unless defined $input_file;
die "$0: --nm must be specified\n" unless defined $nm_path and -x $nm_path;
sub create_stamp_file
{
if (!(-f $stamp_file))
{
open my $fh, '>', $stamp_file
or die "can't open $stamp_file: $!";
close $fh;
}
}
# Skip on Windows and Solaris
if ( $Config{osname} =~ /MSWin32|cygwin|msys/i
|| $Config{osname} =~ /solaris/i)
{
exit 0;
}
# Run nm to scan for symbols. If nm fails at runtime, skip the check.
open my $fh, '-|', "$nm_path -A -u $input_file 2>/dev/null"
or exit 0;
while (<$fh>)
{
# Set of symbols allowed.
# The exclusion of __cxa_atexit is necessary on OpenBSD, which seems
# to insert references to that even in pure C code.
next if /__cxa_atexit/;
# Excluding __tsan_func_exit is necessary when using ThreadSanitizer data
# race detector which uses this function for instrumentation of function
# exit.
next if /__tsan_func_exit/;
# Excluding pthread_exit allows legitimate thread terminations in some
# builds.
next if /pthread_exit/;
# Anything containing "exit" is suspicious.
# (Ideally we should reject abort() too, but there are various scenarios
# where build toolchains insert abort() calls, e.g. to implement
# assert().)
if (/exit/)
{
push @problematic_lines, $_;
}
}
close $fh;
if (@problematic_lines)
{
print "libpq must not be calling any function which invokes exit\n";
print "Problematic symbol references:\n";
print @problematic_lines;
exit 1;
}
# Create stamp file, if required
if (defined($stamp_file))
{
create_stamp_file();
}
exit 0;
|