Don't try to test async-signal-safety, only that
NBD_INTERNAL_FORK_SAFE_ASSERT() works similarly to assert():
- it prints diagnostics to stderr,
- it calls abort().
Some unfortunate gymnastics are necessary to avoid littering the system
with unwanted core dumps.
Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
---
Notes:
v4:
- update Red Hat Copyright Notices in the new files, in accordance with
commit bbf47ffd4ac4 ("Update Red Hat Copyright Notices", 2023-03-04)
- explain the TRUE and FALSE macro definitions in code comments [Eric]
- test that the pattern "`TRUE'" is not present in the output file;
that
is, the passing assertion does not generate unexpected output [Eric]
- do not pick up R-b tags due to the logic update in the last bullet
above
configure.ac | 5 ++
lib/test-fork-safe-assert.c | 66 ++++++++++++++++++++
lib/Makefile.am | 38 +++++++++--
lib/test-fork-safe-assert.sh | 32 ++++++++++
.gitignore | 2 +
5 files changed, 139 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index b6d60c3df6a1..62fe470b6cd5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -132,11 +132,16 @@ dnl Check for various libc functions, all optional.
dnl
dnl posix_fadvise helps to optimise linear reads and writes.
dnl
+dnl When /proc/sys/kernel/core_pattern starts with a pipe (|) symbol, Linux
+dnl ignores "ulimit -c" and (equivalent) setrlimit(RLIMIT_CORE) actions, for
+dnl disabling core dumping. Only prctl() can be used then, for that purpose.
+dnl
dnl strerrordesc_np (glibc only) is preferred over sys_errlist:
dnl
https://lists.fedoraproject.org/archives/list/glibc@lists.fedoraproject.o...
AC_CHECK_FUNCS([\
posix_fadvise \
posix_memalign \
+ prctl \
strerrordesc_np \
valloc])
diff --git a/lib/test-fork-safe-assert.c b/lib/test-fork-safe-assert.c
new file mode 100644
index 000000000000..4a4f6e88ce65
--- /dev/null
+++ b/lib/test-fork-safe-assert.c
@@ -0,0 +1,66 @@
+/* nbd client library in userspace
+ * Copyright Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_PRCTL
+#include <sys/prctl.h>
+#endif
+#include <sys/resource.h>
+
+#undef NDEBUG
+
+#include "internal.h"
+
+/* Define these to verify that NBD_INTERNAL_FORK_SAFE_ASSERT() properly
+ * stringifies the expression passed to it.
+ */
+#define TRUE 1
+#define FALSE 0
+
+int
+main (void)
+{
+ struct rlimit rlimit;
+
+ /* The standard approach for disabling core dumping. Has no effect on Linux if
+ * /proc/sys/kernel/core_pattern starts with a pipe (|) symbol.
+ */
+ if (getrlimit (RLIMIT_CORE, &rlimit) == -1) {
+ perror ("getrlimit");
+ return EXIT_FAILURE;
+ }
+ rlimit.rlim_cur = 0;
+ if (setrlimit (RLIMIT_CORE, &rlimit) == -1) {
+ perror ("setrlimit");
+ return EXIT_FAILURE;
+ }
+
+#ifdef HAVE_PRCTL
+ if (prctl (PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
+ perror ("prctl");
+ return EXIT_FAILURE;
+ }
+#endif
+
+ NBD_INTERNAL_FORK_SAFE_ASSERT (TRUE);
+ NBD_INTERNAL_FORK_SAFE_ASSERT (FALSE);
+ return 0;
+}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 52b525819bde..326b550f90bd 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -25,15 +25,30 @@ generator_built = \
unlocked.h \
$(NULL)
+CLEANFILES += \
+ test-fork-safe-assert.err \
+ $(NULL)
+
EXTRA_DIST = \
$(generator_built) \
libnbd.syms \
+ test-fork-safe-assert.sh \
$(NULL)
lib_LTLIBRARIES = libnbd.la
BUILT_SOURCES = $(generator_built)
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/common/include \
+ -I$(top_srcdir)/common/utils \
+ $(NULL)
+
+AM_CFLAGS = \
+ $(WARNINGS_CFLAGS) \
+ $(NULL)
+
libnbd_la_SOURCES = \
aio.c \
api.c \
@@ -60,13 +75,11 @@ libnbd_la_SOURCES = \
utils.c \
$(NULL)
libnbd_la_CPPFLAGS = \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/common/include \
- -I$(top_srcdir)/common/utils \
+ $(AM_CPPFLAGS) \
-Dsysconfdir=\"$(sysconfdir)\" \
$(NULL)
libnbd_la_CFLAGS = \
- $(WARNINGS_CFLAGS) \
+ $(AM_CFLAGS) \
$(PTHREAD_CFLAGS) \
$(GNUTLS_CFLAGS) \
$(LIBXML2_CFLAGS) \
@@ -86,3 +99,20 @@ libnbd_la_LDFLAGS = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libnbd.pc
+
+# Unit tests.
+
+TESTS = \
+ test-fork-safe-assert.sh \
+ $(NULL)
+
+check_PROGRAMS = \
+ test-fork-safe-assert \
+ $(NULL)
+
+test_fork_safe_assert_SOURCES = \
+ $(top_srcdir)/common/utils/vector.c \
+ errors.c \
+ test-fork-safe-assert.c \
+ utils.c \
+ $(NULL)
diff --git a/lib/test-fork-safe-assert.sh b/lib/test-fork-safe-assert.sh
new file mode 100755
index 000000000000..2cf0a29a4c6d
--- /dev/null
+++ b/lib/test-fork-safe-assert.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+# nbd client library in userspace
+# Copyright Red Hat
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+set +e
+
+./test-fork-safe-assert 2>test-fork-safe-assert.err
+exit_status=$?
+
+set -e
+
+test $exit_status -gt 128
+signal_name=$(kill -l $exit_status)
+test "x$signal_name" = xABRT || test "x$signal_name" = xSIGABRT
+
+ptrn="^test-fork-safe-assert\\.c:[0-9]+: main: Assertion \`FALSE'
failed\\.\$"
+grep -E -q -- "$ptrn" test-fork-safe-assert.err
+grep -v -q "\`TRUE'" test-fork-safe-assert.err
diff --git a/.gitignore b/.gitignore
index 4ebd96519c29..54bc20173f95 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,6 +128,8 @@ Makefile.in
/lib/states-run.c
/lib/states.c
/lib/states.h
+/lib/test-fork-safe-assert
+/lib/test-fork-safe-assert.err
/lib/unlocked.h
/libtool
/ltmain.sh