Merge changes Ib7c80826,I636f8a71,I67669b98 into main

* changes:
  perl: un-autos your conf
  build: declare all the deps as -isystem
  darwin: workaround PROC_PIDLISTFDS on processes with no fds
This commit is contained in:
jade 2024-08-09 19:24:29 +00:00 committed by Gerrit Code Review
commit 790d1079e1
4 changed files with 66 additions and 109 deletions

View file

@ -0,0 +1,15 @@
---
synopsis: "Fix unexpectedly-successful GC failures on macOS"
cls: 1723
issues: fj#446
credits: jade
category: Fixes
---
Has the following happened to you on macOS? This failure has been successfully eliminated, thanks to our successful deployment of advanced successful-failure detection technology (it's just `if (failed && errno == 0)`. Patent pending<sup>not really</sup>):
```
$ nix-store --gc --print-dead
finding garbage collector roots...
error: Listing pid 87261 file descriptors: Undefined error: 0
```

View file

@ -203,23 +203,23 @@ gc_opt = get_option('gc').disable_if(
'address' in get_option('b_sanitize'), 'address' in get_option('b_sanitize'),
error_message: 'gc does far too many memory crimes for ASan' error_message: 'gc does far too many memory crimes for ASan'
) )
boehm = dependency('bdw-gc', required : gc_opt, version : '>=8.2.6') boehm = dependency('bdw-gc', required : gc_opt, version : '>=8.2.6', include_type : 'system')
configdata += { configdata += {
'HAVE_BOEHMGC': boehm.found().to_int(), 'HAVE_BOEHMGC': boehm.found().to_int(),
} }
boost = dependency('boost', required : true, modules : ['container']) boost = dependency('boost', required : true, modules : ['container'], include_type : 'system')
# cpuid only makes sense on x86_64 # cpuid only makes sense on x86_64
cpuid_required = is_x64 ? get_option('cpuid') : false cpuid_required = is_x64 ? get_option('cpuid') : false
cpuid = dependency('libcpuid', 'cpuid', required : cpuid_required) cpuid = dependency('libcpuid', 'cpuid', required : cpuid_required, include_type : 'system')
configdata += { configdata += {
'HAVE_LIBCPUID': cpuid.found().to_int(), 'HAVE_LIBCPUID': cpuid.found().to_int(),
} }
# seccomp only makes sense on Linux # seccomp only makes sense on Linux
seccomp_required = is_linux ? get_option('seccomp-sandboxing') : false seccomp_required = is_linux ? get_option('seccomp-sandboxing') : false
seccomp = dependency('libseccomp', 'seccomp', required : seccomp_required, version : '>=2.5.5') seccomp = dependency('libseccomp', 'seccomp', required : seccomp_required, version : '>=2.5.5', include_type : 'system')
if is_linux and not seccomp.found() if is_linux and not seccomp.found()
warning('Sandbox security is reduced because libseccomp has not been found! Please provide libseccomp if it supports your CPU architecture.') warning('Sandbox security is reduced because libseccomp has not been found! Please provide libseccomp if it supports your CPU architecture.')
endif endif
@ -227,19 +227,24 @@ configdata += {
'HAVE_SECCOMP': seccomp.found().to_int(), 'HAVE_SECCOMP': seccomp.found().to_int(),
} }
libarchive = dependency('libarchive', required : true) libarchive = dependency('libarchive', required : true, include_type : 'system')
brotli = [ brotli = [
dependency('libbrotlicommon', required : true), dependency('libbrotlicommon', required : true, include_type : 'system'),
dependency('libbrotlidec', required : true), dependency('libbrotlidec', required : true, include_type : 'system'),
dependency('libbrotlienc', required : true), dependency('libbrotlienc', required : true, include_type : 'system'),
] ]
openssl = dependency('libcrypto', 'openssl', required : true) openssl = dependency('libcrypto', 'openssl', required : true, include_type : 'system')
# FIXME: confirm we actually support such old versions of aws-sdk-cpp # FIXME: confirm we actually support such old versions of aws-sdk-cpp
aws_sdk = dependency('aws-cpp-sdk-core', required : false, version : '>=1.8') aws_sdk = dependency('aws-cpp-sdk-core', required : false, version : '>=1.8', include_type : 'system')
aws_sdk_transfer = dependency('aws-cpp-sdk-transfer', required : aws_sdk.found(), fallback : ['aws_sdk', 'aws_cpp_sdk_transfer_dep']) aws_sdk_transfer = dependency(
'aws-cpp-sdk-transfer',
required : aws_sdk.found(),
fallback : ['aws_sdk', 'aws_cpp_sdk_transfer_dep'],
include_type : 'system',
)
if aws_sdk.found() if aws_sdk.found()
# The AWS pkg-config adds -std=c++11. # The AWS pkg-config adds -std=c++11.
# https://github.com/aws/aws-sdk-cpp/issues/2673 # https://github.com/aws/aws-sdk-cpp/issues/2673
@ -259,7 +264,12 @@ if aws_sdk.found()
) )
endif endif
aws_s3 = dependency('aws-cpp-sdk-s3', required : aws_sdk.found(), fallback : ['aws_sdk', 'aws_cpp_sdk_s3_dep']) aws_s3 = dependency(
'aws-cpp-sdk-s3',
required : aws_sdk.found(),
fallback : ['aws_sdk', 'aws_cpp_sdk_s3_dep'],
include_type : 'system',
)
if aws_s3.found() if aws_s3.found()
# The AWS pkg-config adds -std=c++11. # The AWS pkg-config adds -std=c++11.
# https://github.com/aws/aws-sdk-cpp/issues/2673 # https://github.com/aws/aws-sdk-cpp/issues/2673
@ -276,30 +286,30 @@ configdata += {
'ENABLE_S3': aws_s3.found().to_int(), 'ENABLE_S3': aws_s3.found().to_int(),
} }
sqlite = dependency('sqlite3', 'sqlite', version : '>=3.6.19', required : true) sqlite = dependency('sqlite3', 'sqlite', version : '>=3.6.19', required : true, include_type : 'system')
sodium = dependency('libsodium', 'sodium', required : true) sodium = dependency('libsodium', 'sodium', required : true, include_type : 'system')
curl = dependency('libcurl', 'curl', required : true) curl = dependency('libcurl', 'curl', required : true, include_type : 'system')
editline = dependency('libeditline', 'editline', version : '>=1.14', required : true) editline = dependency('libeditline', 'editline', version : '>=1.14', required : true, include_type : 'system')
lowdown = dependency('lowdown', version : '>=0.9.0', required : true) lowdown = dependency('lowdown', version : '>=0.9.0', required : true, include_type : 'system')
# HACK(Qyriad): rapidcheck's pkg-config doesn't include the libs lol # HACK(Qyriad): rapidcheck's pkg-config doesn't include the libs lol
# Note: technically we 'check' for rapidcheck twice, for the internal-api-docs handling above, # Note: technically we 'check' for rapidcheck twice, for the internal-api-docs handling above,
# but Meson will cache the result of the first one, and the required : arguments are different. # but Meson will cache the result of the first one, and the required : arguments are different.
rapidcheck_meson = dependency('rapidcheck', required : enable_tests) rapidcheck_meson = dependency('rapidcheck', required : enable_tests, include_type : 'system')
rapidcheck = declare_dependency(dependencies : rapidcheck_meson, link_args : ['-lrapidcheck']) rapidcheck = declare_dependency(dependencies : rapidcheck_meson, link_args : ['-lrapidcheck'])
gtest = [ gtest = [
dependency('gtest', required : enable_tests), dependency('gtest', required : enable_tests, include_type : 'system'),
dependency('gtest_main', required : enable_tests), dependency('gtest_main', required : enable_tests, include_type : 'system'),
dependency('gmock', required : enable_tests), dependency('gmock', required : enable_tests, include_type : 'system'),
dependency('gmock_main', required : enable_tests), dependency('gmock_main', required : enable_tests, include_type : 'system'),
] ]
toml11 = dependency('toml11', version : '>=3.7.0', required : true, method : 'cmake') toml11 = dependency('toml11', version : '>=3.7.0', required : true, method : 'cmake', include_type : 'system')
pegtl = dependency( pegtl = dependency(
'pegtl', 'pegtl',
@ -307,9 +317,10 @@ pegtl = dependency(
required : true, required : true,
method : 'cmake', method : 'cmake',
modules : [ 'taocpp::pegtl' ], modules : [ 'taocpp::pegtl' ],
include_type : 'system',
) )
nlohmann_json = dependency('nlohmann_json', required : true) nlohmann_json = dependency('nlohmann_json', required : true, include_type : 'system')
# lix-doc is a Rust project provided via buildInputs and unfortunately doesn't have any way to be detected. # lix-doc is a Rust project provided via buildInputs and unfortunately doesn't have any way to be detected.
# Just declare it manually to resolve this. # Just declare it manually to resolve this.

View file

@ -1,84 +0,0 @@
AC_INIT(nix-perl, m4_esyscmd([bash -c "echo -n $(cat ../.version)$VERSION_SUFFIX"]))
AC_CONFIG_SRCDIR(MANIFEST)
AC_CONFIG_AUX_DIR(../config)
CFLAGS=
CXXFLAGS=
AC_PROG_CC
AC_PROG_CXX
AC_CANONICAL_HOST
# Use 64-bit file system calls so that we can support files > 2 GiB.
AC_SYS_LARGEFILE
AC_DEFUN([NEED_PROG],
[
AC_PATH_PROG($1, $2)
if test -z "$$1"; then
AC_MSG_ERROR([$2 is required])
fi
])
NEED_PROG(perl, perl)
NEED_PROG(curl, curl)
NEED_PROG(bzip2, bzip2)
NEED_PROG(xz, xz)
# Test that Perl has the open/fork feature (Perl 5.8.0 and beyond).
AC_MSG_CHECKING([whether Perl is recent enough])
if ! $perl -e 'open(FOO, "-|", "true"); while (<FOO>) { print; }; close FOO or die;'; then
AC_MSG_RESULT(no)
AC_MSG_ERROR([Your Perl version is too old. Lix requires Perl 5.8.0 or newer.])
fi
AC_MSG_RESULT(yes)
# Figure out where to install Perl modules.
AC_MSG_CHECKING([for the Perl installation prefix])
perlversion=$($perl -e 'use Config; print $Config{version};')
perlarchname=$($perl -e 'use Config; print $Config{archname};')
AC_SUBST(perllibdir, [${libdir}/perl5/site_perl/$perlversion/$perlarchname])
AC_MSG_RESULT($perllibdir)
# Look for libsodium.
PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"])
# Check for the required Perl dependencies (DBI and DBD::SQLite).
perlFlags="-I$perllibdir"
AC_ARG_WITH(dbi, AC_HELP_STRING([--with-dbi=PATH],
[prefix of the Perl DBI library]),
perlFlags="$perlFlags -I$withval")
AC_ARG_WITH(dbd-sqlite, AC_HELP_STRING([--with-dbd-sqlite=PATH],
[prefix of the Perl DBD::SQLite library]),
perlFlags="$perlFlags -I$withval")
AC_MSG_CHECKING([whether DBD::SQLite works])
if ! $perl $perlFlags -e 'use DBI; use DBD::SQLite;' 2>&5; then
AC_MSG_RESULT(no)
AC_MSG_FAILURE([The Perl modules DBI and/or DBD::SQLite are missing.])
fi
AC_MSG_RESULT(yes)
AC_SUBST(perlFlags)
PKG_CHECK_MODULES([NIX], [nix-store])
NEED_PROG([NIX], [nix])
# Expand all variables in config.status.
test "$prefix" = NONE && prefix=$ac_default_prefix
test "$exec_prefix" = NONE && exec_prefix='${prefix}'
for name in $ac_subst_vars; do
declare $name="$(eval echo "${!name}")"
declare $name="$(eval echo "${!name}")"
declare $name="$(eval echo "${!name}")"
done
rm -f Makefile.config
ln -sfn ../mk mk
AC_CONFIG_FILES([])
AC_OUTPUT

View file

@ -56,14 +56,29 @@ void DarwinLocalStore::findPlatformRoots(UncheckedRoots & unchecked)
while (fdBufSize > fds.size() * sizeof(struct proc_fdinfo)) { while (fdBufSize > fds.size() * sizeof(struct proc_fdinfo)) {
// Reserve some extra size so we don't fail too much // Reserve some extra size so we don't fail too much
fds.resize((fdBufSize + fdBufSize / 8) / sizeof(struct proc_fdinfo)); fds.resize((fdBufSize + fdBufSize / 8) / sizeof(struct proc_fdinfo));
errno = 0;
fdBufSize = proc_pidinfo( fdBufSize = proc_pidinfo(
pid, PROC_PIDLISTFDS, 0, fds.data(), fds.size() * sizeof(struct proc_fdinfo) pid, PROC_PIDLISTFDS, 0, fds.data(), fds.size() * sizeof(struct proc_fdinfo)
); );
// errno == 0???! Yes, seriously. This is because macOS has a
// broken syscall wrapper for proc_pidinfo that has no way of
// dealing with the system call successfully returning 0. It
// takes the -1 error result from the errno-setting syscall
// wrapper and turns it into a 0 result. But what if the system
// call actually returns 0? Then you get an errno of success.
//
// https://github.com/apple-opensource/xnu/blob/4f43d4276fc6a87f2461a3ab18287e4a2e5a1cc0/libsyscall/wrappers/libproc/libproc.c#L100-L110
// https://git.lix.systems/lix-project/lix/issues/446#issuecomment-5483
// FB14695751
if (fdBufSize <= 0) { if (fdBufSize <= 0) {
if (errno == 0) {
break;
} else {
throw SysError("Listing pid %1% file descriptors", pid); throw SysError("Listing pid %1% file descriptors", pid);
} }
} }
}
fds.resize(fdBufSize / sizeof(struct proc_fdinfo)); fds.resize(fdBufSize / sizeof(struct proc_fdinfo));
for (auto fd : fds) { for (auto fd : fds) {