1.0.2-10 - Evolution of the previous (rhbz#1478089, rhbz#1487787)
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
This commit is contained in:
parent
c61edd4d30
commit
95877b0e29
@ -1,4 +1,4 @@
|
||||
From 8bfe49d79c1b7ae1aa4b7b22b627afa40a4a08d2 Mon Sep 17 00:00:00 2001
|
||||
From a7014f6d411685a5691be0f59c0634e165771811 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||
Subject: [PATCH 1/6] Med: qblog.h: better explanation + behaviour of
|
||||
@ -12,7 +12,10 @@ put a better description for the macro. Also based on poor user
|
||||
experience in case that feature does not work well, say because
|
||||
the linker deliberately changes the previously settled visibility
|
||||
of the section boundary symbols (happened in ld from binutils-2.29,
|
||||
fix is forthcoming), tweak the assertion message a bit:
|
||||
fix is forthcoming), tweak the assertion message a bit, together
|
||||
with an extension of the general intro to point that macro out.
|
||||
Also play fair, include the <assert.h> header, which this macro
|
||||
requires.
|
||||
|
||||
- use case:
|
||||
/usr/sbin/pacemakerd --features
|
||||
@ -23,21 +26,59 @@ fix is forthcoming), tweak the assertion message a bit:
|
||||
|
||||
- after:
|
||||
pacemakerd: utils.c:69: common:
|
||||
Assertion `("non-empty callsite section", QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP)' failed.
|
||||
Assertion `"non-empty callsite section" && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP' failed.
|
||||
|
||||
Inspired by the suggestion of Ferenc Wágner (for the subsequent
|
||||
commit, actually).
|
||||
|
||||
And regarding:
|
||||
> as a side effect, it can ensure the boundary-denoting symbols for
|
||||
> the target collection area are kept alive with some otherwise unkind
|
||||
> linkers
|
||||
this was actually empirically discovered in one particular combination
|
||||
with ld.bfd @ binutils 2.29, and extensively with 2.29.1 (placing here
|
||||
a forward reference for the following commits that elaborate on the
|
||||
libqb-target cross-combination matrix and the findings).
|
||||
|
||||
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||
---
|
||||
include/qb/qblog.h | 17 ++++++++++++-----
|
||||
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||
include/qb/qblog.h | 34 +++++++++++++++++++++++++++++-----
|
||||
1 file changed, 29 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
|
||||
index 3cb4eef..d38449d 100644
|
||||
index 3cb4eef..d39803f 100644
|
||||
--- a/include/qb/qblog.h
|
||||
+++ b/include/qb/qblog.h
|
||||
@@ -268,11 +268,18 @@ typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs);
|
||||
@@ -42,6 +42,10 @@ extern "C" {
|
||||
#undef QB_HAVE_ATTRIBUTE_SECTION
|
||||
#endif /* S_SPLINT_S */
|
||||
|
||||
+#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
||||
+#include <assert.h> /* possibly needed for QB_LOG_INIT_DATA */
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* @file qblog.h
|
||||
* The logging API provides four main parts (basics, filtering, threading & blackbox).
|
||||
@@ -64,6 +68,17 @@ extern "C" {
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
+ * @note
|
||||
+ * In practice, such a minimalistic approach hardly caters real use cases.
|
||||
+ * Following section discusses the customization. Moreover, it's quite
|
||||
+ * vital to instrument the target user of this logging subsystem with
|
||||
+ * @c QB_LOG_INIT_DATA() macro placed in the top file scope in an exactly
|
||||
+ * one source file (preferably the main one) to be compiled into the
|
||||
+ * resulting binary. This is a self-defensive measure for when the
|
||||
+ * linker-assisted collection of callsite data silently fails, which
|
||||
+ * could otherwise go unnoticed, causing troubles down the road.
|
||||
+ *
|
||||
+ *
|
||||
* @par Configuring log targets.
|
||||
* A log target can be syslog, stderr, the blackbox, stdout, or a text file.
|
||||
* By default only syslog is enabled.
|
||||
@@ -268,11 +283,20 @@ typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs);
|
||||
extern struct qb_log_callsite QB_ATTR_SECTION_START[];
|
||||
extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
||||
|
||||
@ -46,18 +87,20 @@ index 3cb4eef..d38449d 100644
|
||||
- void name(void); \
|
||||
- void name(void) \
|
||||
- { if (QB_ATTR_SECTION_START == QB_ATTR_SECTION_STOP) assert(0); } \
|
||||
+/* optional on-demand self-check of (1) toolchain sanity and (2) non-void
|
||||
+ * (implied by the justifying existence of at least a single logging callsite
|
||||
+ * ~ qb_logt invocation) employment of logging subsystem in the target binary,
|
||||
+ * which is presumably assured by it's author as of relying on this macro;
|
||||
+/* optional on-demand self-check of (1) toolchain sanity (prerequisite for
|
||||
+ * the logging subsystem to work properly) and (2) non-void active use of
|
||||
+ * logging (satisfied with a justifying existence of a logging callsite as
|
||||
+ * defined with a @c qb_logt invocation) at the target binary, which is
|
||||
+ * presumably assured by it's author as of relying on this very macro;
|
||||
+ * only effective when link-time ("run-time amortizing") callsite collection
|
||||
+ * is available and may be extended in future for more in-depth self-validation
|
||||
+ */
|
||||
+ * is; as a side effect, it can ensure the boundary-denoting symbols for the
|
||||
+ * target collection area are kept alive with some otherwise unkind linkers;
|
||||
+ * may be extended in future for more in-depth self-validation */
|
||||
+#define QB_LOG_INIT_DATA(name) \
|
||||
+ void name(void); \
|
||||
+ void name(void) \
|
||||
+ { assert(("non-empty callsite section", \
|
||||
+ QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP)); } \
|
||||
+ { assert("non-empty callsite section" \
|
||||
+ && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP); } \
|
||||
void __attribute__ ((constructor)) name(void);
|
||||
#else
|
||||
#define QB_LOG_INIT_DATA(name)
|
||||
|
@ -1,4 +1,4 @@
|
||||
From d6491970c1e050dae3fc9b65fd34e4c170ca50a0 Mon Sep 17 00:00:00 2001
|
||||
From ccfe20a89b3099f17f22971995ace787356ed5f4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||
Subject: [PATCH 2/6] build: configure: run attribute section test through
|
||||
@ -15,14 +15,14 @@ of the run-time error signalling through assertions.
|
||||
|
||||
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||
---
|
||||
configure.ac | 20 +++++++++++---------
|
||||
1 file changed, 11 insertions(+), 9 deletions(-)
|
||||
configure.ac | 22 +++++++++++++---------
|
||||
1 file changed, 13 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 22630ba..727b8f0 100644
|
||||
index 22630ba..478194c 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -620,15 +620,17 @@ AC_SUBST(HAVE_SLOW_TESTS)
|
||||
@@ -620,15 +620,19 @@ AC_SUBST(HAVE_SLOW_TESTS)
|
||||
if test "x${GCC}" = xyes; then
|
||||
AC_MSG_CHECKING([whether GCC supports __attribute__((section()) + ld supports orphan sections])
|
||||
if test "x${ac_cv_link_attribute_section}" = x ; then
|
||||
@ -40,9 +40,11 @@ index 22630ba..727b8f0 100644
|
||||
+ [[#include <assert.h>
|
||||
+ extern void * __start___verbose, * __stop___verbose;]],
|
||||
+ [[static int my_var __attribute__((section("__verbose"))) = 5;
|
||||
+ assert(("non-empty data section", __start___verbose != __stop___verbose));
|
||||
+ assert(("no data section value loss", my_var == 5));
|
||||
+ ]]),
|
||||
+ assert("non-empty data section"
|
||||
+ && __start___verbose != __stop___verbose);
|
||||
+ assert("no data section value loss"
|
||||
+ && my_var == 5);]]
|
||||
+ ),
|
||||
+ [gcc_has_attribute_section=yes],
|
||||
+ [gcc_has_attribute_section=no]
|
||||
+ )
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 9e0f0f6d8045a1bd5482a6e704300a324458a96a Mon Sep 17 00:00:00 2001
|
||||
From c489cb378cd8ad7a7a089067e39b65b0c359c60b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||
Subject: [PATCH 3/6] tests: new sort of tests dubbed "functional", cover
|
||||
@ -14,7 +14,9 @@ checking harness, usually available through "make check", but not to be
|
||||
confused with regular unit + broader tests). These test are meant to be
|
||||
compiled on demand only, not during the standard building routine, for
|
||||
which a trick leveraging GNUmakefile-Makefile precedence with GNU make
|
||||
was devised.
|
||||
was devised (GNU make/gmake already required by configure script for
|
||||
other reasons [some pattern-based matching not available with FreeBSD's
|
||||
default "make", IIRC], so this introduces no new build dependency).
|
||||
|
||||
The respective new tests are meant to simulate logging variants in two
|
||||
different library consumption models:
|
||||
@ -56,7 +58,7 @@ Current state for this matrix, in which participants 1. - 3. map like:
|
||||
3. ~ libX(Y) [a.k.a. interlib]
|
||||
and where "X(Y)" denotes "X linked with linker Y":
|
||||
X(a) .. ld.bfd < 2.29
|
||||
X(b) .. ld.bfd = 2.29 (and likely on),
|
||||
X(b) .. ld.bfd = 2.29 (and only 2.29),
|
||||
goes like this:
|
||||
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
@ -68,6 +70,18 @@ goes like this:
|
||||
# x = b # BAD[*A] | BAD[*B] : BAD[*C] # BAD[*1] | BAD[*C] : BAD[*3] #
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
|
||||
whereas if we swap 2.29 for 2.29.1, i.e., X(b) .. ld.bfd = 2.29.1, we
|
||||
can observe a somewhat simpler story (DEP ~ "depends"):
|
||||
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
#client(x)# libqb(a) usage # libqb(b) usage #
|
||||
# vvv #---------+---------+---------+---------+---------+---------+
|
||||
# V # direct | libX(a) : libX(b) # direct | libX(a) : libX(b) #
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
# x = a # OK | OK : DEP[*J] # BAD[*1] | BAD[*1] : BAD[*L] #
|
||||
# x = b # DEP[*I] | DEP[*I] : DEP[*K] # BAD[*1] | BAD[*1] : BAD[*L] #
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
|
||||
[*1] client logging not working
|
||||
[*2] interlib logging not working
|
||||
[*3] both client and interlib logging not working
|
||||
@ -81,15 +95,29 @@ goes like this:
|
||||
[*D] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which makes it boil down just to [*1] (hypothesis: mere internal
|
||||
self-reference to the section's boundary symbols makes them
|
||||
overcome some kind of garbage collection at the linkage stage,
|
||||
so they are exposed even they wouldn't be otherwise as demonstrated
|
||||
with the initial, plain case of [*3])
|
||||
overcome some kind of symbol garbage collection at the linkage
|
||||
stage, so they are exposed even they wouldn't be otherwise as
|
||||
demonstrated with the initial, plain case of [*3])
|
||||
|
||||
[*I] boils down to [*1], unless QB_LOG_INIT_DATA used on client side,
|
||||
which makes it, likely through self-reference keepalive (see
|
||||
below) work OK
|
||||
[*J] boils down to [*2], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which makes it, likely through self-reference keepalive (see
|
||||
below) work OK
|
||||
[*K] boils down to [*3], unless QB_LOG_INIT_DATA used on both client
|
||||
and interlib side, which makes it, likely through self-reference
|
||||
keepalive (see below) work OK (it's expected that this a mere
|
||||
composite of situations [*I] and [*J] with consequences as stated)
|
||||
[*L] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side
|
||||
(sufficient?), which makes it, likely through self-reference
|
||||
keepalive (see below) boil down just to [*1]
|
||||
|
||||
Note: as observed with [*D] case (libqb linked with ld.bfd < 2.29
|
||||
whereas interlib and its client linked with ld.bfd = 2.29), the exact
|
||||
availability of a working logging doesn't depend solely on the linkers
|
||||
in question, but generally (further investigation out of scope) the
|
||||
conclusion is that when 2.29+ ld.bfd is involved somewhere in the chain
|
||||
conclusion is that when 2.29 ld.bfd is involved somewhere in the chain
|
||||
of logging-related discrete compilation units, also (self-)referencing
|
||||
of the section's boundary denoting symbols is a deciding factor whether
|
||||
particular logging source will be honored. This may be a result of
|
||||
@ -114,10 +142,10 @@ Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||
tests/functional/log_interlib_client.c | 64 ++++++
|
||||
tests/functional/log_interlib_client.err | 4 +
|
||||
tests/functional/log_internal/Makefile.am | 23 +++
|
||||
tests/functional/log_test_client.sh | 22 +++
|
||||
tests/functional/log_test_interlib_client.sh | 22 +++
|
||||
tests/functional/log_test_mock.sh | 285 +++++++++++++++++++++++++++
|
||||
18 files changed, 704 insertions(+), 2 deletions(-)
|
||||
tests/functional/log_test_client.sh | 22 ++
|
||||
tests/functional/log_test_interlib_client.sh | 22 ++
|
||||
tests/functional/log_test_mock.sh | 289 +++++++++++++++++++++++++++
|
||||
16 files changed, 706 insertions(+), 2 deletions(-)
|
||||
create mode 100644 tests/functional/GNUmakefile
|
||||
create mode 100644 tests/functional/Makefile.am
|
||||
create mode 100644 tests/functional/log.am
|
||||
@ -133,7 +161,7 @@ Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||
create mode 100755 tests/functional/log_test_mock.sh
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 727b8f0..db7bc68 100644
|
||||
index 478194c..274b49c 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -13,7 +13,7 @@ AC_CONFIG_SRCDIR([lib/ringbuffer.c])
|
||||
@ -145,7 +173,7 @@ index 727b8f0..db7bc68 100644
|
||||
dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from
|
||||
dnl normal compilation. When a failure occurs, it will then display the full
|
||||
dnl command line
|
||||
@@ -715,6 +715,9 @@ AC_CONFIG_FILES([Makefile
|
||||
@@ -717,6 +717,9 @@ AC_CONFIG_FILES([Makefile
|
||||
lib/libqb.pc
|
||||
tools/Makefile
|
||||
tests/Makefile
|
||||
@ -155,7 +183,7 @@ index 727b8f0..db7bc68 100644
|
||||
tests/test.conf
|
||||
examples/Makefile
|
||||
docs/Makefile
|
||||
@@ -722,6 +725,8 @@ AC_CONFIG_FILES([Makefile
|
||||
@@ -724,6 +727,8 @@ AC_CONFIG_FILES([Makefile
|
||||
docs/html.dox
|
||||
docs/man.dox])
|
||||
|
||||
@ -672,10 +700,10 @@ index 0000000..59c5555
|
||||
+diff -u ../log_interlib_client.err log_interlib_client.err.real
|
||||
diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh
|
||||
new file mode 100755
|
||||
index 0000000..fb2c02c
|
||||
index 0000000..4489718
|
||||
--- /dev/null
|
||||
+++ b/tests/functional/log_test_mock.sh
|
||||
@@ -0,0 +1,285 @@
|
||||
@@ -0,0 +1,289 @@
|
||||
+#!/bin/sh
|
||||
+# Copyright 2017 Red Hat, Inc.
|
||||
+#
|
||||
@ -736,6 +764,7 @@ index 0000000..fb2c02c
|
||||
+mock_args="-r fedora-27-${arch}"
|
||||
+pkg_binutils_228=binutils-2.28-14.fc27
|
||||
+pkg_binutils_229=binutils-2.29-6.fc27
|
||||
+#pkg_binutils_229=binutils-2.29.1-2.fc28 # alternatively test with 2.29.1
|
||||
+
|
||||
+#
|
||||
+# prettified reporters
|
||||
@ -875,7 +904,7 @@ index 0000000..fb2c02c
|
||||
+ | sed -n '/\.tar/{s|\.tar\.[^.]*$||;p;q}')"
|
||||
+
|
||||
+ _resultsdir="_results/$(date '+%y%m%d_%H%M%S')_${_libqb_descriptor}"
|
||||
+ test -z "${_makevars}" || _resultsdir="${_resultsdir}_sc"
|
||||
+ test -z "${_makevars}" || _resultsdir="${_resultsdir}_nsc"
|
||||
+ mkdir -p "${_resultsdir}"
|
||||
+ rm -f -- "${_resultsdir}/*"
|
||||
+
|
||||
@ -895,16 +924,19 @@ index 0000000..fb2c02c
|
||||
+ esac
|
||||
+
|
||||
+ do_progress "installing ${_pkg_binutils_libqb} so as to build" \
|
||||
+ " libqb [${_outfile_qb}]"
|
||||
+ "libqb [${_outfile_qb}]"
|
||||
+ do_install "${_pkg_binutils_libqb}"
|
||||
+
|
||||
+ do_progress "building ${_libqb_descriptor_path} with" \
|
||||
+ " ${_pkg_binutils_libqb} [${_outfile_qb}]"
|
||||
+ "${_pkg_binutils_libqb} [${_outfile_qb}]"
|
||||
+ do_buildsrpm "${_libqb_descriptor_path}" "${_dist}"
|
||||
+
|
||||
+ do_progress "installing ${_libqb_descriptor}-based packages" \
|
||||
+ " built with ${_pkg_binutils_libqb} [${_outfile_qb}]"
|
||||
+ "built with ${_pkg_binutils_libqb} [${_outfile_qb}]"
|
||||
+ do_install "${_libqb_descriptor}"
|
||||
+ # from now on, we can work fully offline, also to speed
|
||||
+ # the whole thing up (and not to bother the mirrors)
|
||||
+ mock_args="${mock_args} --offline"
|
||||
+
|
||||
+ for _pkg_binutils_interlib in none "${pkg_binutils_228}" "${pkg_binutils_229}"; do
|
||||
+
|
||||
@ -919,11 +951,11 @@ index 0000000..fb2c02c
|
||||
+ none) ;;
|
||||
+ *)
|
||||
+ do_progress "installing ${_pkg_binutils_interlib}" \
|
||||
+ " so as to build interlib [${_outfile}]"
|
||||
+ "so as to build interlib [${_outfile}]"
|
||||
+ do_install "${_pkg_binutils_interlib}"
|
||||
+
|
||||
+ do_progress "building interlib with ${_libqb_descriptor_archive}" \
|
||||
+ " + ${_pkg_binutils_interlib} [${_outfile}]"
|
||||
+ "+ ${_pkg_binutils_interlib} [${_outfile}]"
|
||||
+ do_compile_interlib "${_libqb_descriptor_archive}" "${_makevars}"
|
||||
+ ;;
|
||||
+ esac
|
||||
@ -940,10 +972,10 @@ index 0000000..fb2c02c
|
||||
+ esac
|
||||
+
|
||||
+ do_progress "installing ${_pkg_binutils_client}" \
|
||||
+ " so as to build ${_client} [${_outfile_client}]"
|
||||
+ "so as to build ${_client} [${_outfile_client}]"
|
||||
+ do_install "${_pkg_binutils_client}"
|
||||
+ do_progress "building ${_client} with ${_libqb_descriptor_archive}" \
|
||||
+ " + ${_pkg_binutils_client} [${_outfile_client}]"
|
||||
+ "+ ${_pkg_binutils_client} [${_outfile_client}]"
|
||||
+ do_compile_and_test_client "${_libqb_descriptor_archive}" \
|
||||
+ "${_client}" "${_resultsdir}" \
|
||||
+ "${_outfile_client}" "${_makevars}"
|
||||
|
490
04-Med-add-extra-run-time-client-libqb-checks-that-logg.patch
Normal file
490
04-Med-add-extra-run-time-client-libqb-checks-that-logg.patch
Normal file
@ -0,0 +1,490 @@
|
||||
From 0c8500a0c15f54250ce93c724451c36cde8b4499 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||
Subject: [PATCH 4/6] Med: add extra run-time (client, libqb) checks that
|
||||
logging will work
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The table at the bottom concludes how the test matrix overview
|
||||
introduced with a message for the preceding commit (also introducing
|
||||
log_test_mock.sh runner which got reused here) looks as of this
|
||||
refreshed sanity check, once QB_LOG_INIT_DATA macro at hand gets
|
||||
applied (meaning "for non-libqb logging participants" so as not
|
||||
complicate the matrix further). That macro is nothing triggered
|
||||
directly, it will just plant a constructor-like function (to be
|
||||
invoked automatically early in the execution) that will run through
|
||||
the checks (one original and couple of new ones as of this changeset).
|
||||
|
||||
Note that for libqb users, this implies a new link dependency on libdl,
|
||||
because they may opt-in for refreshed QB_LOG_INIT_DATA sanity check that
|
||||
calls out to dlopen/dlsym/dladdr directly in case of "attribute section"
|
||||
being available for the particular platform, and hence immediately needs
|
||||
those symbols resolved in link time. Hence, add this conditional link
|
||||
dependency to libqb.pc pkg-config file under Libs variable -- we
|
||||
actually restore the occurrence of "-ldl" there as it used to be present
|
||||
until commit 56754d0. While doing so, also move immediate link
|
||||
dependencies of libqb (if any, currently not but that may be
|
||||
a regression arising from the cleanup related to the mentioned commit)
|
||||
represented with the LIBS autoconf variable under Libs.private variable
|
||||
in libqb.pc, where it belongs per pkg-config documentation.
|
||||
|
||||
The promised table follows, but first as a recap, "X(Y)" denotes
|
||||
"X linked with linker Y":
|
||||
X(a) .. ld.bfd < 2.29
|
||||
X(b) .. ld.bfd = 2.29 (and only 2.29)
|
||||
|
||||
goes like this (values in <angle brackets> denote non-trivial change
|
||||
[not mere rewording] introduced as of this commit, in comparison to
|
||||
the table stated in the preceding commit):
|
||||
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
#client(x)# libqb(a) usage # libqb(b) usage #
|
||||
# vvv #---------+---------+---------+---------+---------+---------+
|
||||
# V # direct | libX(a) : libX(b) # direct | libX(a) : libX(b) #
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
# x = a # OK | OK : BAD[*2] #<BAD[*E]>|<BAD[*F]>:<BAD[*G]>#
|
||||
# x = b # BAD[*A] | BAD[*B] : BAD[*C] #<BAD[*E]>|<BAD[*F]>:<BAD[*G]>#
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
|
||||
whereas if we swap 2.29 for 2.29.1, i.e., X(b) .. ld.bfd = 2.29.1, we
|
||||
can observe a somewhat simpler story (DEP ~ "depends"):
|
||||
|
||||
Woefully, nothing changes if we swap binutils 2.29.1 for 2.29, i.e.,
|
||||
X(b) .. ld.bfd = 2.29.1. The second table from the previous commit
|
||||
hence remains the same. The added sanity checks are useful nonetheless,
|
||||
consider for example, that attribute-section-less libqb is what gets
|
||||
run-time linked to an attribute-section-full target. The most precise
|
||||
check we could use -- a custom logger function applied in a self-test
|
||||
scheme -- is not available at the point the macro-defined function gets
|
||||
invoked, simply because qb_log_init hasn't been invoked by the time
|
||||
that constructor gets triggered. However, what we can do is to add
|
||||
a non-trapping libqb-residing reverse-testing of the client space that
|
||||
invokes qb_log_init (being intrusive all of a sudden at some unknown
|
||||
execution point, as opposed to constructor-like function, seems pretty
|
||||
bad idea + libqb as a library is a mere helper, not an undertaker :)
|
||||
-- this check can at least announce, via syslog (the only
|
||||
initially enabled logging target) that the target logging won't work.
|
||||
|
||||
After incorporating such a change (and extending log_test_mock.sh so as
|
||||
to capture syslog stream within the container), nothing changes with the
|
||||
table above, but desirably changes with "X(b) .. ld.bfd = 2.29.1" one:
|
||||
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
#client(x)# libqb(a) usage # libqb(b) usage #
|
||||
# vvv #---------+---------+---------+---------+---------+---------+
|
||||
# V # direct | libX(a) : libX(b) # direct | libX(a) : libX(b) #
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
# x = a # OK | OK : DEP[*J] #<BAD[*M]>|<BAD[*M]>:<BAD[*L]>#
|
||||
# x = b #<DEP[*N]>| DEP[*I] :<DEP[*O]>#<BAD[*M]>|<BAD[*M]>:<BAD[*L]>#
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
|
||||
[*1] client logging not working
|
||||
[*2] interlib logging not working
|
||||
[*3] both client and interlib logging not working
|
||||
|
||||
[*A] boils down to [*1], unless QB_LOG_INIT_DATA used on client side,
|
||||
which then fails on
|
||||
"non-empty implicit callsite section, otherwise target's linkage at
|
||||
fault and logging would not work reliably"
|
||||
assertion
|
||||
[*B] boils down to [*1], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which then fails on
|
||||
"non-empty implicit callsite section, otherwise target's linkage at
|
||||
fault and logging would not work reliably"
|
||||
assertion
|
||||
[*C] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which then fails on
|
||||
"non-empty implicit callsite section, otherwise target's linkage at
|
||||
fault and logging would not work reliably"
|
||||
assertion
|
||||
[*E] boils down to [*1], unless QB_LOG_INIT_DATA used on client side,
|
||||
which then fails on
|
||||
"target's callsite section self-observable, otherwise target's
|
||||
and/or libqb's linkage at fault and logging would not work reliably"
|
||||
assertion
|
||||
[*F] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which then fails on
|
||||
"libqb's callsite section non-empty, otherwise libqb's linkage at
|
||||
fault and logging would not work reliably"
|
||||
assertion
|
||||
[*G] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which then fails on
|
||||
"target's callsite section self-observable, otherwise target's and/or
|
||||
libqb's linkage at fault and logging would not work reliably"
|
||||
assertion
|
||||
|
||||
[*I] boils down to [*1], unless QB_LOG_INIT_DATA used on client side,
|
||||
which makes it, likely through self-reference keepalive (see
|
||||
below) work OK
|
||||
[*J] boils down to [*2], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which makes it, likely through self-reference keepalive (see
|
||||
below) work OK
|
||||
[*K] boils down to [*3]
|
||||
in addition, syslog carries this error:
|
||||
"target chain supplied section not observed by libqb, target's and/or
|
||||
libqb's linkage at fault and logging of the target will not work
|
||||
reliably"
|
||||
logged by libqb proper
|
||||
[*L] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side
|
||||
(sufficient?), which makes it, likely through self-reference
|
||||
keepalive (see below) boil down just to [*1];
|
||||
in addition, syslog carries this error:
|
||||
"target chain supplied section not observed by libqb, target's and/or
|
||||
libqb's linkage at fault and logging of the target will not work
|
||||
reliably"
|
||||
logged by libqb proper
|
||||
[*M] boils down to [*1];
|
||||
in addition, syslog carries this error:
|
||||
"target chain supplied section not observed by libqb, target's and/or
|
||||
libqb's linkage at fault and logging of the target will not work
|
||||
reliably"
|
||||
logged by libqb proper
|
||||
[*N] boils down to [*M], unless QB_LOG_INIT_DATA used on client side,
|
||||
which makes it, likely through self-reference keepalive (see
|
||||
below) work OK
|
||||
[*O] boils down to [*K], unless QB_LOG_INIT_DATA used on both client
|
||||
and interlib side, which makes it, likely through self-reference
|
||||
keepalive (see below) work OK (it's expected that this a mere
|
||||
composite of situations [*I] and [*J] with consequences as stated)
|
||||
|
||||
Note: the only problematic (i.e. not captured automatically by the
|
||||
QB_LOG_INIT_DATA macro presumably utilized at every non-libqb logging
|
||||
system participant in the form of a discrete compilation unit)
|
||||
combination with 2.29 is the one intersecting at "BAD[*2]" pertaining
|
||||
"everything but interlib compiled with ld.bfd < 2.29". It would, of
|
||||
course, be solvable as well, but presumably not in an easy way, and
|
||||
that use case should not be as frequent.
|
||||
|
||||
Takeway: whenever your target (library or client program) actively
|
||||
utilizes logging (meaning it emits at least a single log message),
|
||||
YOU ARE strongly ENCOURAGED TO USE QB_LOG_INIT_DATA macro function
|
||||
at (exactly) one of the source code files (presumably the main one)
|
||||
per respective target's compilation unit. It will alleviate the
|
||||
hassles possibly caused by downgrading libqb to the linker-vs-libqb
|
||||
incompatibly compiled one or in similar circumstances arising merely
|
||||
from the linker behaviour change, which the current build system/code
|
||||
quake is all about.
|
||||
|
||||
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||
---
|
||||
configure.ac | 1 +
|
||||
include/qb/qblog.h | 63 ++++++++++++++++++++++++++++---
|
||||
lib/libqb.pc.in | 3 +-
|
||||
lib/log.c | 44 +++++++++++++++++++++
|
||||
tests/functional/Makefile.am | 3 +-
|
||||
tests/functional/log.am | 2 +-
|
||||
tests/functional/log_external/Makefile.am | 8 +++-
|
||||
tests/functional/log_test_mock.sh | 13 ++++++-
|
||||
tests/functional/syslog-stdout.py | 49 ++++++++++++++++++++++++
|
||||
9 files changed, 173 insertions(+), 13 deletions(-)
|
||||
create mode 100755 tests/functional/syslog-stdout.py
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 274b49c..5769e60 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -642,6 +642,7 @@ if test "x${GCC}" = xyes; then
|
||||
AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1,
|
||||
[Enabling code using __attribute__((section))])
|
||||
PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
|
||||
+ AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS])
|
||||
fi
|
||||
fi
|
||||
|
||||
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
|
||||
index d39803f..9474c16 100644
|
||||
--- a/include/qb/qblog.h
|
||||
+++ b/include/qb/qblog.h
|
||||
@@ -44,6 +44,7 @@ extern "C" {
|
||||
|
||||
#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
||||
#include <assert.h> /* possibly needed for QB_LOG_INIT_DATA */
|
||||
+#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -283,20 +284,70 @@ typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs);
|
||||
extern struct qb_log_callsite QB_ATTR_SECTION_START[];
|
||||
extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
||||
|
||||
-/* optional on-demand self-check of (1) toolchain sanity (prerequisite for
|
||||
+/* Related to the next macro that is -- unlike this one -- a public API */
|
||||
+#ifndef _GNU_SOURCE
|
||||
+#define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \
|
||||
+ _Pragma(QB_PP_STRINGIFY(GCC warning QB_PP_STRINGIFY( \
|
||||
+ without "_GNU_SOURCE" defined (directly or not) \
|
||||
+ qb_log_init_data cannot check sanity of libqb proper)))
|
||||
+#else
|
||||
+#define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \
|
||||
+ /* libqb sanity (locating libqb by it's relatively unique \
|
||||
+ -- and currently only such per-linkage global one -- \
|
||||
+ non-functional symbol, due to possible confusion otherwise) */ \
|
||||
+ if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli) \
|
||||
+ && (work_handle = dlopen(work_dli.dli_fname, \
|
||||
+ RTLD_LOCAL|RTLD_LAZY)) != NULL) { \
|
||||
+ work_s1 = (struct qb_log_callsite *) \
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_START_STR); \
|
||||
+ work_s2 = (struct qb_log_callsite *) \
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_STOP_STR); \
|
||||
+ assert("libqb's callsite section observable, otherwise libqb's \
|
||||
+linkage at fault and logging would not work reliably" \
|
||||
+ && work_s1 != NULL && work_s2 != NULL); \
|
||||
+ assert("libqb's callsite section non-empty, otherwise libqb's \
|
||||
+linkage at fault and logging would not work reliably" \
|
||||
+ && work_s1 != work_s2); \
|
||||
+ dlclose(work_handle); }
|
||||
+#endif
|
||||
+
|
||||
+/**
|
||||
+ * Optional on-demand self-check of (1) toolchain sanity (prerequisite for
|
||||
* the logging subsystem to work properly) and (2) non-void active use of
|
||||
* logging (satisfied with a justifying existence of a logging callsite as
|
||||
* defined with a @c qb_logt invocation) at the target binary, which is
|
||||
* presumably assured by it's author as of relying on this very macro;
|
||||
* only effective when link-time ("run-time amortizing") callsite collection
|
||||
* is; as a side effect, it can ensure the boundary-denoting symbols for the
|
||||
- * target collection area are kept alive with some otherwise unkind linkers;
|
||||
- * may be extended in future for more in-depth self-validation */
|
||||
+ * target collection area are kept alive with some otherwise unkind linkers.
|
||||
+ *
|
||||
+ * Applying this macro in the target program/library is strongly recommended
|
||||
+ * whenever the logging as framed by this header file is in use.
|
||||
+ * Moreover, it's important to state that using this check while not ensuring
|
||||
+ * @c _GNU_SOURCE macro definition is present at compile-time means only half
|
||||
+ * of the available sanity checking will be performed, possibly resulting
|
||||
+ * in libqb's own internally logged messages being lost without warning.
|
||||
+ */
|
||||
#define QB_LOG_INIT_DATA(name) \
|
||||
void name(void); \
|
||||
- void name(void) \
|
||||
- { assert("non-empty callsite section" \
|
||||
- && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP); } \
|
||||
+ void name(void) { \
|
||||
+ void *work_handle; struct qb_log_callsite *work_s1, *work_s2; \
|
||||
+ Dl_info work_dli; \
|
||||
+ /* our own (target's) sanity */ \
|
||||
+ if ((work_handle = dlopen(NULL, RTLD_LOCAL|RTLD_LAZY)) != NULL) { \
|
||||
+ work_s1 = (struct qb_log_callsite *) \
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_START_STR); \
|
||||
+ work_s2 = (struct qb_log_callsite *) \
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_STOP_STR); \
|
||||
+ assert("target's callsite section self-observable, otherwise \
|
||||
+target's and/or libqb's linkage at fault and logging would not work \
|
||||
+reliably" \
|
||||
+ && work_s1 != NULL && work_s2 != NULL); } \
|
||||
+ QB_NONAPI_LOG_INIT_DATA_EXTRA_; \
|
||||
+ /* original "cherry on the cake" check */ \
|
||||
+ assert("non-empty implicit callsite section, otherwise target's \
|
||||
+linkage at fault and logging would not work reliably" \
|
||||
+ && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP); } \
|
||||
void __attribute__ ((constructor)) name(void);
|
||||
#else
|
||||
#define QB_LOG_INIT_DATA(name)
|
||||
diff --git a/lib/libqb.pc.in b/lib/libqb.pc.in
|
||||
index 8a8d0ba..37d27b7 100644
|
||||
--- a/lib/libqb.pc.in
|
||||
+++ b/lib/libqb.pc.in
|
||||
@@ -7,5 +7,6 @@ Name: libqb
|
||||
Version: @PACKAGE_VERSION@
|
||||
Description: libqb
|
||||
Requires:
|
||||
-Libs: -L${libdir} -lqb @LIBS@
|
||||
+Libs: -L${libdir} -lqb @client_dlopen_LIBS@
|
||||
+Libs.private: @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
diff --git a/lib/log.c b/lib/log.c
|
||||
index bfd218f..f30b8d8 100644
|
||||
--- a/lib/log.c
|
||||
+++ b/lib/log.c
|
||||
@@ -853,6 +853,18 @@ qb_log_init(const char *name, int32_t facility, uint8_t priority)
|
||||
{
|
||||
int32_t l;
|
||||
enum qb_log_target_slot i;
|
||||
+#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
||||
+ void *work_handle; struct qb_log_callsite *work_s1, *work_s2;
|
||||
+ Dl_info work_dli;
|
||||
+#endif /* QB_HAVE_ATTRIBUTE_SECTION */
|
||||
+ /* cannot reuse single qb_log invocation in various contexts
|
||||
+ through the variables (when section attribute in use),
|
||||
+ hence this indirection */
|
||||
+ enum {
|
||||
+ preinit_err_none,
|
||||
+ preinit_err_target_sec,
|
||||
+ preinit_err_target_empty,
|
||||
+ } preinit_err = preinit_err_none;
|
||||
|
||||
l = pthread_rwlock_init(&_listlock, NULL);
|
||||
assert(l == 0);
|
||||
@@ -871,6 +883,25 @@ qb_log_init(const char *name, int32_t facility, uint8_t priority)
|
||||
|
||||
qb_log_dcs_init();
|
||||
#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
||||
+ /* sanity check that target chain supplied QB_ATTR_SECTION_ST{ART,OP}
|
||||
+ symbols and hence the local references to them are not referencing
|
||||
+ the proper libqb's ones (locating libqb-self by it's relatively
|
||||
+ unique -- and currently only such per-linkage global one --
|
||||
+ non-functional symbol, due to possible confusion otherwise) */
|
||||
+ if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli)
|
||||
+ && (work_handle = dlopen(work_dli.dli_fname,
|
||||
+ RTLD_LOCAL|RTLD_LAZY)) != NULL) {
|
||||
+ work_s1 = (struct qb_log_callsite *)
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_START_STR);
|
||||
+ work_s2 = (struct qb_log_callsite *)
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_STOP_STR);
|
||||
+ if (work_s1 == QB_ATTR_SECTION_START
|
||||
+ || work_s2 == QB_ATTR_SECTION_STOP) {
|
||||
+ preinit_err = preinit_err_target_sec;
|
||||
+ } else if (work_s1 == work_s2) {
|
||||
+ preinit_err = preinit_err_target_empty;
|
||||
+ }
|
||||
+ }
|
||||
qb_log_callsites_register(QB_ATTR_SECTION_START, QB_ATTR_SECTION_STOP);
|
||||
dl_iterate_phdr(_log_so_walk_callback, NULL);
|
||||
_log_so_walk_dlnames();
|
||||
@@ -884,6 +915,19 @@ qb_log_init(const char *name, int32_t facility, uint8_t priority)
|
||||
_log_target_state_set(&conf[QB_LOG_SYSLOG], QB_LOG_STATE_ENABLED);
|
||||
(void)qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
|
||||
QB_LOG_FILTER_FILE, "*", priority);
|
||||
+
|
||||
+ if (preinit_err == preinit_err_target_sec)
|
||||
+ qb_util_log(LOG_ERR, "target chain supplied section not"
|
||||
+ " observed by libqb, target's and/or"
|
||||
+ " libqb's linkage at fault and"
|
||||
+ " logging of the target will not"
|
||||
+ " work reliably");
|
||||
+ else if (preinit_err == preinit_err_target_empty) {
|
||||
+ qb_util_log(LOG_WARNING, "target chain supplied section empty,"
|
||||
+ " target's linkage at fault and"
|
||||
+ " logging of the target will not"
|
||||
+ " work reliably");
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
diff --git a/tests/functional/Makefile.am b/tests/functional/Makefile.am
|
||||
index 72f551e..c079009 100644
|
||||
--- a/tests/functional/Makefile.am
|
||||
+++ b/tests/functional/Makefile.am
|
||||
@@ -19,5 +19,6 @@
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
EXTRA_DIST = GNUmakefile log_client.err log_interlib_client.err \
|
||||
- log_test_client.sh log_test_interlib_client.sh log_test_mock.sh
|
||||
+ log_test_client.sh log_test_interlib_client.sh \
|
||||
+ log_test_mock.sh syslog-stdout.py
|
||||
SUBDIRS = log_external log_internal
|
||||
diff --git a/tests/functional/log.am b/tests/functional/log.am
|
||||
index 5fe1ae7..0753fa5 100644
|
||||
--- a/tests/functional/log.am
|
||||
+++ b/tests/functional/log.am
|
||||
@@ -20,7 +20,7 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
CLEANFILES = log_client.err.real log_interlib_client.err.real
|
||||
|
||||
-AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
+AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
|
||||
noinst_PROGRAMS = log_client log_interlib_client
|
||||
# cannot use {check,noinst}_LTLIBRARIES because it leads to solely static lib
|
||||
diff --git a/tests/functional/log_external/Makefile.am b/tests/functional/log_external/Makefile.am
|
||||
index 36aa0af..ca1c8a5 100644
|
||||
--- a/tests/functional/log_external/Makefile.am
|
||||
+++ b/tests/functional/log_external/Makefile.am
|
||||
@@ -19,5 +19,9 @@
|
||||
|
||||
include ../log.am
|
||||
|
||||
-log_client_LDFLAGS = -lqb
|
||||
-liblog_inter_la_LIBADD = -lqb
|
||||
+# while linking with system-wide version of libqb, we are still pursuing
|
||||
+# local in-tree header file, hence we need to link with dynamic linking
|
||||
+# library (which is a prerequisite for using QB_LOG_INIT_DATA defined
|
||||
+# in qblog.h) explicitly
|
||||
+log_client_LDFLAGS = -lqb @client_dlopen_LIBS@
|
||||
+liblog_inter_la_LIBADD = -lqb @client_dlopen_LIBS@
|
||||
diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh
|
||||
index 4489718..5900f6c 100755
|
||||
--- a/tests/functional/log_test_mock.sh
|
||||
+++ b/tests/functional/log_test_mock.sh
|
||||
@@ -165,10 +165,19 @@ do_compile_and_test_client () {
|
||||
-exec rm -- {} \;"
|
||||
;;
|
||||
esac
|
||||
+ mock ${mock_args} --copyin "syslog-stdout.py" "builddir"
|
||||
mock ${mock_args} --shell "( cd \"builddir/build/BUILD/$1\"; ./configure )"
|
||||
mock ${mock_args} --shell \
|
||||
- "make -C \"builddir/build/BUILD/$1/tests/functional/log_external\" \
|
||||
- check-TESTS \"TESTS=../${_logfile}.sh\" $5" \
|
||||
+ "python3 builddir/syslog-stdout.py \
|
||||
+ >\"builddir/build/BUILD/$1/tests/functional/log_external/.syslog\" & \
|
||||
+ { sleep 2; make -C \"builddir/build/BUILD/$1/tests/functional/log_external\" \
|
||||
+ check-TESTS \"TESTS=../${_logfile}.sh\" $5; } \
|
||||
+ && ! test -s \"builddir/build/BUILD/$1/tests/functional/log_external/.syslog\"; \
|
||||
+ ret_ec=\$?; \
|
||||
+ ( cd \"builddir/build/BUILD/$1/tests/functional/log_external\"; \
|
||||
+ cat .syslog >> test-suite.log; \
|
||||
+ echo SYSLOG-begin; cat .syslog; echo SYSLOG-end ); \
|
||||
+ ret () { return \$1; }; ret \${ret_ec}" \
|
||||
&& _result="${_result}_good" \
|
||||
|| _result="${_result}_bad"
|
||||
mock ${mock_args} --copyout \
|
||||
diff --git a/tests/functional/syslog-stdout.py b/tests/functional/syslog-stdout.py
|
||||
new file mode 100755
|
||||
index 0000000..a0a761b
|
||||
--- /dev/null
|
||||
+++ b/tests/functional/syslog-stdout.py
|
||||
@@ -0,0 +1,49 @@
|
||||
+#!/usr/bin/python3
|
||||
+# Copyright 2017 Red Hat, Inc.
|
||||
+#
|
||||
+# Author: Jan Pokorny <jpokorny@redhat.com>
|
||||
+#
|
||||
+# This file is part of libqb.
|
||||
+#
|
||||
+# libqb 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.1 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+import socket
|
||||
+from atexit import register
|
||||
+from os import remove
|
||||
+from sys import argv
|
||||
+
|
||||
+# no locking, but anyway
|
||||
+try:
|
||||
+ remove("/dev/log")
|
||||
+except FileNotFoundError:
|
||||
+ pass
|
||||
+sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
||||
+sock.bind("/dev/log")
|
||||
+
|
||||
+def shutdown():
|
||||
+ sock.close()
|
||||
+ remove("/dev/log")
|
||||
+
|
||||
+def main(*argv):
|
||||
+ register(shutdown)
|
||||
+ while True:
|
||||
+ try:
|
||||
+ b = sock.recv(4096)
|
||||
+ # flushing is crucial here
|
||||
+ print(">>> " + str(b, 'ascii').split(' ', 3)[-1], flush=True)
|
||||
+ except IOError:
|
||||
+ pass
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ main(*argv)
|
||||
--
|
||||
2.14.2
|
||||
|
@ -1,257 +0,0 @@
|
||||
From b883cc548ff1d487af6cd5bee49c5b386f91df4d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||
Subject: [PATCH 4/6] Med: add extra run-time client-side sanity check that
|
||||
logging will work
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The table at the bottom concludes how the test matrix overview
|
||||
introduced with a message for the preceding commit (also introducing
|
||||
log_test_mock.sh runner which got reused here) looks as of this
|
||||
refreshed sanity check, once it (QB_LOG_INIT_DATA macro) gets applied
|
||||
(meaning "for non-libqb logging participants" so as not complicate
|
||||
the matrix further).
|
||||
|
||||
Note that for libqb users, this implies a new link dependency on libdl,
|
||||
because they may opt-in for refreshed QB_LOG_INIT_DATA sanity check that
|
||||
calls out to dlopen/dlsym/dladdr directly in case of "attribute section"
|
||||
being available for the particular platform, and hence immediately needs
|
||||
those symbols resolved in link time. Hence, add this conditional link
|
||||
dependency to libqb.pc pkg-config file under Libs variable -- we
|
||||
actually restore the occurrence of "-ldl" there as it used to be present
|
||||
until commit 56754d0. While doing so, also move immediate link
|
||||
dependencies of libqb (if any, currently not but that may be
|
||||
a regression arising from the cleanup related to the mentioned commit)
|
||||
represented with the LIBS autoconf variable under Libs.private variable
|
||||
in libqb.pc, where it belongs per pkg-config documentation.
|
||||
|
||||
The promised table follows, but first as a recap, "X(Y)" denotes
|
||||
"X linked with linker Y":
|
||||
X(a) .. ld.bfd < 2.29
|
||||
X(b) .. ld.bfd = 2.29 (and likely on)
|
||||
|
||||
goes like this (values in <angle brackets> denote non-trivial change
|
||||
[not mere rewording] introduced as of this commit, in comparison to
|
||||
the table stated in the preceding commit):
|
||||
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
#client(x)# libqb(a) usage # libqb(b) usage #
|
||||
# vvv #---------+---------+---------+---------+---------+---------+
|
||||
# V # direct | libX(a) : libX(b) # direct | libX(a) : libX(b) #
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
# x = a # OK | OK : BAD[*2] #<BAD[*E]>|<BAD[*F]>:<BAD[*G]>#
|
||||
# x = b # BAD[*A] | BAD[*B] : BAD[*C] #<BAD[*E]>|<BAD[*F]>:<BAD[*G]>#
|
||||
+=========+=========+=========+=========+=========+=========+=========+
|
||||
|
||||
[*1] client logging not working
|
||||
[*2] interlib logging not working
|
||||
[*3] both client and interlib logging not working
|
||||
|
||||
[*A] boils down to [*1], unless QB_LOG_INIT_DATA used on client side,
|
||||
which then fails on
|
||||
"non-empty implicit callsite section, otherwise target's linkage at
|
||||
fault and logging would not work reliably"
|
||||
assertion
|
||||
[*B] boils down to [*1], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which then fails on
|
||||
"non-empty implicit callsite section, otherwise target's linkage at
|
||||
fault and logging would not work reliably"
|
||||
assertion
|
||||
[*C] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which then fails on
|
||||
"non-empty implicit callsite section, otherwise target's linkage at
|
||||
fault and logging would not work reliably"
|
||||
assertion
|
||||
[*E] boils down to [*1], unless QB_LOG_INIT_DATA used on client side,
|
||||
which then fails on
|
||||
"target's callsite section self-observable, otherwise target's
|
||||
linkage at fault and logging would not work reliably"
|
||||
assertion
|
||||
[*F] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which then fails on
|
||||
"libqb's callsite section non-empty, otherwise libqb's linkage at
|
||||
fault and logging would not work reliably"
|
||||
assertion
|
||||
[*G] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
|
||||
which then fails on
|
||||
"target's callsite section self-observable, otherwise target's linkage
|
||||
at fault and logging would not work reliably"
|
||||
assertion
|
||||
|
||||
Note: the only problematic (i.e. not captured automatically by the
|
||||
QB_LOG_INIT_DATA macro presumably utilized at every non-libqb logging
|
||||
system participant in the form of a discrete compilation unit)
|
||||
combination is the one intersecting at "BAD[*2]" pertaining "everything
|
||||
but interlib compiled with ld.bfd < 2.29". It would, of course, be
|
||||
solvable as well, but presumably not in an easy way, and that use case
|
||||
should not be as frequent.
|
||||
|
||||
Takeway: whenever your target (library or client program) actively
|
||||
utilizes logging (meaning it emits at least a single log message),
|
||||
YOU ARE strongly ENCOURAGED TO USE QB_LOG_INIT_DATA macro function
|
||||
at (exactly) one of the source code files (presumably the main one)
|
||||
per respective target's compilation unit. It will alleviate the
|
||||
hassles possibly caused by downgrading libqb to the linker-vs-libqb
|
||||
incompatibly compiled one or in similar circumstances arising merely
|
||||
from the linker behaviour change, which the current build system/code
|
||||
quake is all about.
|
||||
|
||||
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||
---
|
||||
configure.ac | 1 +
|
||||
include/qb/qblog.h | 67 ++++++++++++++++++++++++++++---
|
||||
lib/libqb.pc.in | 3 +-
|
||||
tests/functional/log.am | 2 +-
|
||||
tests/functional/log_external/Makefile.am | 8 +++-
|
||||
5 files changed, 72 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index db7bc68..5601302 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -640,6 +640,7 @@ if test "x${GCC}" = xyes; then
|
||||
AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1,
|
||||
[Enabling code using __attribute__((section))])
|
||||
PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
|
||||
+ AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS])
|
||||
fi
|
||||
fi
|
||||
|
||||
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
|
||||
index d38449d..e49c86c 100644
|
||||
--- a/include/qb/qblog.h
|
||||
+++ b/include/qb/qblog.h
|
||||
@@ -42,6 +42,11 @@ extern "C" {
|
||||
#undef QB_HAVE_ATTRIBUTE_SECTION
|
||||
#endif /* S_SPLINT_S */
|
||||
|
||||
+#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
||||
+#include <assert.h>
|
||||
+#include <dlfcn.h>
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* @file qblog.h
|
||||
* The logging API provides four main parts (basics, filtering, threading & blackbox).
|
||||
@@ -268,18 +273,70 @@ typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs);
|
||||
extern struct qb_log_callsite QB_ATTR_SECTION_START[];
|
||||
extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
||||
|
||||
-/* optional on-demand self-check of (1) toolchain sanity and (2) non-void
|
||||
+/* Related to the next macro, which is -- contrary to this -- public API */
|
||||
+#ifndef _GNU_SOURCE
|
||||
+#warning "without _GNU_SOURCE defined (directly or not), QB_LOG_INIT_DATA cannot check libqb's own sanity"
|
||||
+#define QB_NONAPI_LOG_INIT_DATA_EXTRA_
|
||||
+#else
|
||||
+#define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \
|
||||
+ /* libqb sanity (locating libqb by it's relatively unique \
|
||||
+ -- and currently only such per-linkage global one -- \
|
||||
+ non-functional symbol, due to possible confusion otherwise) */ \
|
||||
+ if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli) \
|
||||
+ && (work_handle = dlopen(work_dli.dli_fname, \
|
||||
+ RTLD_LOCAL|RTLD_LAZY)) != NULL) { \
|
||||
+ work_s1 = (struct qb_log_callsite *) \
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_START_STR); \
|
||||
+ assert(("libqb's callsite section not 1st in global resolution, \
|
||||
+otherwise target's linkage at fault and logging would not work reliably",\
|
||||
+ work_s2 != work_s1)); \
|
||||
+ work_s2 = (struct qb_log_callsite *) \
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_STOP_STR); \
|
||||
+ assert(("libqb's callsite section non-empty, otherwise libqb's \
|
||||
+linkage at fault and logging would not work reliably", \
|
||||
+ work_s1 != work_s2)); \
|
||||
+ dlclose(work_handle); }
|
||||
+#endif
|
||||
+
|
||||
+/**
|
||||
+ * Optional on-demand self-check of (1) toolchain sanity and (2) non-void
|
||||
* (implied by the justifying existence of at least a single logging callsite
|
||||
* ~ qb_logt invocation) employment of logging subsystem in the target binary,
|
||||
* which is presumably assured by it's author as of relying on this macro;
|
||||
* only effective when link-time ("run-time amortizing") callsite collection
|
||||
- * is available and may be extended in future for more in-depth self-validation
|
||||
+ * is.
|
||||
+ *
|
||||
+ * Applying this macro in the target program/library is strongly recommended
|
||||
+ * whenever the logging as framed by this header file is in use. Moreover,
|
||||
+ * it's important to state that using this check while not ensuring _GNU_SOURCE
|
||||
+ * macro definition is present at compile-time means only half of the available
|
||||
+ * sanity checking will be performed, possibly resulting in libqb's own
|
||||
+ * internally logged messages being lost.
|
||||
*/
|
||||
#define QB_LOG_INIT_DATA(name) \
|
||||
void name(void); \
|
||||
- void name(void) \
|
||||
- { assert(("non-empty callsite section", \
|
||||
- QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP)); } \
|
||||
+ void name(void) { \
|
||||
+ void *work_handle; struct qb_log_callsite *work_s1, *work_s2; \
|
||||
+ Dl_info work_dli; \
|
||||
+ /* our own (target's) sanity */ \
|
||||
+ if ((work_handle = dlopen(NULL, RTLD_LOCAL|RTLD_LAZY)) != NULL) { \
|
||||
+ work_s1 = (struct qb_log_callsite *) \
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_START_STR); \
|
||||
+ work_s2 = (struct qb_log_callsite *) \
|
||||
+ dlsym(work_handle, QB_ATTR_SECTION_STOP_STR); \
|
||||
+ assert(("target's callsite section self-observable, otherwise \
|
||||
+target's linkage at fault and logging would not work reliably", \
|
||||
+ work_s1 != NULL && work_s2 != NULL)); \
|
||||
+ work_s2 = (struct qb_log_callsite *) \
|
||||
+ dlsym(RTLD_DEFAULT, QB_ATTR_SECTION_START_STR); \
|
||||
+ assert(("target's callsite section 1st in global resolution, \
|
||||
+otherwise target's linkage at fault and logging would not work reliably",\
|
||||
+ work_s1 == work_s2)); } \
|
||||
+ QB_NONAPI_LOG_INIT_DATA_EXTRA_; \
|
||||
+ /* original "cherry on the cake" check, possibly expendable */ \
|
||||
+ assert(("non-empty implicit callsite section, otherwise target's \
|
||||
+linkage at fault and logging would not work reliably", \
|
||||
+ QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP)); } \
|
||||
void __attribute__ ((constructor)) name(void);
|
||||
#else
|
||||
#define QB_LOG_INIT_DATA(name)
|
||||
diff --git a/lib/libqb.pc.in b/lib/libqb.pc.in
|
||||
index 8a8d0ba..37d27b7 100644
|
||||
--- a/lib/libqb.pc.in
|
||||
+++ b/lib/libqb.pc.in
|
||||
@@ -7,5 +7,6 @@ Name: libqb
|
||||
Version: @PACKAGE_VERSION@
|
||||
Description: libqb
|
||||
Requires:
|
||||
-Libs: -L${libdir} -lqb @LIBS@
|
||||
+Libs: -L${libdir} -lqb @client_dlopen_LIBS@
|
||||
+Libs.private: @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
diff --git a/tests/functional/log.am b/tests/functional/log.am
|
||||
index 5fe1ae7..0753fa5 100644
|
||||
--- a/tests/functional/log.am
|
||||
+++ b/tests/functional/log.am
|
||||
@@ -20,7 +20,7 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
CLEANFILES = log_client.err.real log_interlib_client.err.real
|
||||
|
||||
-AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
+AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
|
||||
noinst_PROGRAMS = log_client log_interlib_client
|
||||
# cannot use {check,noinst}_LTLIBRARIES because it leads to solely static lib
|
||||
diff --git a/tests/functional/log_external/Makefile.am b/tests/functional/log_external/Makefile.am
|
||||
index 36aa0af..ca1c8a5 100644
|
||||
--- a/tests/functional/log_external/Makefile.am
|
||||
+++ b/tests/functional/log_external/Makefile.am
|
||||
@@ -19,5 +19,9 @@
|
||||
|
||||
include ../log.am
|
||||
|
||||
-log_client_LDFLAGS = -lqb
|
||||
-liblog_inter_la_LIBADD = -lqb
|
||||
+# while linking with system-wide version of libqb, we are still pursuing
|
||||
+# local in-tree header file, hence we need to link with dynamic linking
|
||||
+# library (which is a prerequisite for using QB_LOG_INIT_DATA defined
|
||||
+# in qblog.h) explicitly
|
||||
+log_client_LDFLAGS = -lqb @client_dlopen_LIBS@
|
||||
+liblog_inter_la_LIBADD = -lqb @client_dlopen_LIBS@
|
||||
--
|
||||
2.14.2
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 509beb47f2494e7fe207180266401288da1b6b6d Mon Sep 17 00:00:00 2001
|
||||
From e911aae9c4474cc16d06be02fabcacde9f8d54b5 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||
Subject: [PATCH 5/6] High: bare fix for libqb logging not working with
|
||||
@ -34,7 +34,10 @@ above.
|
||||
And then for 2.29.1 release of binutils once again, as someone actually
|
||||
noticed something went overboard with the 2.29 changes:
|
||||
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=21964
|
||||
http://lists.gnu.org/archive/html/bug-binutils/2017-08/msg00195.html
|
||||
(overview of the original bug discussion, rather than directly
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=21964, which is
|
||||
a result of a conflct resolution when restoring bugzilla backup)
|
||||
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=487b6440dad57440939fab7afdd84a218b612796
|
||||
|
||||
At least that change doesn't invalidate all the effort being put into
|
||||
@ -87,7 +90,8 @@ So further extensions were devised to cover both consumption models:
|
||||
libqb_la_LIBADD, and with a little bit of further fiddling, it works
|
||||
as desired (note that double occurrence of "-Wl,foo.t" equivalent
|
||||
present at some stages of sorting this trick turned out to be,
|
||||
surprisingly, counter-productive);
|
||||
surprisingly, counter-productive, which should now demistify the
|
||||
very existence of effectively empty qblog_script_noop.ld file);
|
||||
|
||||
NOTE: some forms of libtool distribution (debian + derivatives ones
|
||||
in particular) undermine natural transitive dependency propagation
|
||||
@ -99,12 +103,30 @@ So further extensions were devised to cover both consumption models:
|
||||
of consuming libqb outside of it's own playground is hardly
|
||||
the Right Thing) if portability is important, nonetheless!
|
||||
|
||||
On the address of linker script workaround, there are linkers out there
|
||||
that do not support the trick, for instance:
|
||||
- ld.gold from binutils (but it has hardly ever been working with
|
||||
orphan sections, anyway:
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=22291)
|
||||
- ancient versions of ld.bfd, e.g. 10+ years old one used as a native
|
||||
system linker even in the most recent releases of FreeBSD, unless
|
||||
GCC toolchain is used instead
|
||||
If these are hit when (because) the compiler has already demonstrated it
|
||||
supports section attribute, the build system configuration is forcibly
|
||||
stopped, simply to stay conceptually compatible with the prior state in
|
||||
which the affinity to leverage that feature hasn't been called off
|
||||
under any circumstances. One is, however, able to achieve exactly
|
||||
this behaviour with --enable-nosection-fallback switch, but if some
|
||||
other participants in the logging, possibly linked with a more friendly
|
||||
linker, do utilize this orphan section, logging may silently break
|
||||
(another reason to require an explicit sign-off).
|
||||
|
||||
Last but not least, libqb itself needs to be linked with the mentioned
|
||||
"-Wl,foo.t" equivalent for its own outgoing log messages to be honoured,
|
||||
which is already achieved with the arrangement for b. above, and by
|
||||
experiments, further redefinition of those boundary denoting symbols
|
||||
as weak was necessary so as to make them truly global within libqb.so
|
||||
proper (at least with binutils 2.29).
|
||||
"-Wl,foo.t" equivalent for its own outgoing log messages to be honoured
|
||||
under all circumstances, which is already achieved with the arrangement
|
||||
for b. above, and by experiments, further redefinition of those boundary
|
||||
denoting symbols as weak was necessary so as to make them truly global
|
||||
within libqb.so proper (at least with binutils 2.29).
|
||||
|
||||
* * *
|
||||
|
||||
@ -112,7 +134,7 @@ Finally, let's have a look how the already well-known test matrix
|
||||
overview changes as of this commit, but first as a recap,
|
||||
"X(Y)" denotes "X linked with linker Y":
|
||||
X(a) .. ld.bfd < 2.29
|
||||
X(b) .. ld.bfd = 2.29 (and likely on)
|
||||
X(b) .. ld.bfd = 2.29 (+ 2.29.1 and hopefully on)
|
||||
|
||||
and here you are (values in <angle brackets> denote non-trivial change
|
||||
[not mere rewording] introduced as of this commit, in comparison to the
|
||||
@ -174,35 +196,38 @@ References:
|
||||
|
||||
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||
---
|
||||
configure.ac | 90 +++++++++++++++++++++++++++++++++++++++++-------
|
||||
lib/Makefile.am | 67 +++++++++++++++++++++++++++++++++++
|
||||
lib/log.c | 7 ++++
|
||||
lib/qblog_script.la.in | 15 ++++++++
|
||||
lib/qblog_script.ld.in | 17 +++++++++
|
||||
lib/qblog_script_noop.ld | 1 +
|
||||
7 files changed, 184 insertions(+), 13 deletions(-)
|
||||
configure.ac | 146 +++++++++++++++++++++++++++++++++++++++++------
|
||||
lib/Makefile.am | 67 ++++++++++++++++++++++
|
||||
lib/libqb.pc.in | 6 ++
|
||||
lib/log.c | 7 +++
|
||||
lib/qblog_script.la.in | 15 +++++
|
||||
lib/qblog_script.ld.in | 25 ++++++++
|
||||
lib/qblog_script_noop.ld | 1 +
|
||||
7 files changed, 249 insertions(+), 18 deletions(-)
|
||||
create mode 100644 lib/qblog_script.la.in
|
||||
create mode 100644 lib/qblog_script.ld.in
|
||||
create mode 100644 lib/qblog_script_noop.ld
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 5601302..6eda2dd 100644
|
||||
index 5769e60..57875c8 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -501,6 +501,12 @@ AC_ARG_ENABLE([debug],
|
||||
@@ -501,6 +501,14 @@ AC_ARG_ENABLE([debug],
|
||||
AC_ARG_ENABLE([coverage],
|
||||
[AS_HELP_STRING([--enable-coverage],[coverage analysis of the codebase])])
|
||||
|
||||
+AC_ARG_ENABLE([interlib-deps],
|
||||
+ [AS_HELP_STRING([--disable-interlib-deps],
|
||||
+ [disable inter-library dependencies (might break builds)])],
|
||||
+ [enable_interlib_deps="$enableval"],
|
||||
+ [enable_interlib_deps="yes"])
|
||||
+ [disable inter-library dependencies (might break builds)])])
|
||||
+
|
||||
+AC_ARG_ENABLE([nosection-fallback],
|
||||
+ [AS_HELP_STRING([--enable-nosection-fallback],
|
||||
+ [allow (logging compat-breaking?) fallback when orphan section dead-ended])])
|
||||
+
|
||||
AC_ARG_ENABLE([slow-tests],
|
||||
[AS_HELP_STRING([--enable-slow-tests],[build and run slow tests])])
|
||||
|
||||
@@ -609,6 +615,19 @@ else
|
||||
@@ -609,6 +617,19 @@ else
|
||||
COVERAGE_LDFLAGS=""
|
||||
fi
|
||||
|
||||
@ -212,17 +237,17 @@ index 5601302..6eda2dd 100644
|
||||
+# override the libtool variable by force because the current
|
||||
+# arrangement relies on transitive dependency propagation
|
||||
+AC_MSG_NOTICE([Enabling inter-library dependencies: $enable_interlib_deps])
|
||||
+if test "${enable_interlib_deps}" == "yes"; then
|
||||
+ link_all_deplibs=yes
|
||||
+else
|
||||
+if test "x${enable_interlib_deps}" = xno; then
|
||||
+ link_all_deplibs=no
|
||||
+else
|
||||
+ link_all_deplibs=yes
|
||||
+fi
|
||||
+
|
||||
+# --- slow tests ---
|
||||
if test "x${enable_slow_tests}" = xyes ; then
|
||||
AC_DEFINE([HAVE_SLOW_TESTS], 1,[have slow tests])
|
||||
AC_MSG_NOTICE([Enabling Slow tests])
|
||||
@@ -618,31 +637,74 @@ AC_SUBST(HAVE_SLOW_TESTS)
|
||||
@@ -618,33 +639,120 @@ AC_SUBST(HAVE_SLOW_TESTS)
|
||||
|
||||
# --- callsite sections ---
|
||||
if test "x${GCC}" = xyes; then
|
||||
@ -237,18 +262,22 @@ index 5601302..6eda2dd 100644
|
||||
[[#include <assert.h>
|
||||
- extern void * __start___verbose, * __stop___verbose;]],
|
||||
- [[static int my_var __attribute__((section("__verbose"))) = 5;
|
||||
- assert(("non-empty data section", __start___verbose != __stop___verbose));
|
||||
- assert(("no data section value loss", my_var == 5));
|
||||
- ]]),
|
||||
- assert("non-empty data section"
|
||||
- && __start___verbose != __stop___verbose);
|
||||
- assert("no data section value loss"
|
||||
- && my_var == 5);]]
|
||||
- ),
|
||||
- [gcc_has_attribute_section=yes],
|
||||
+ extern int __start___verbose[], __stop___verbose[];
|
||||
+ int test(void) {
|
||||
+ static int my_var __attribute__((section("__verbose"))) = 3;
|
||||
+ assert(("L:non-empty data section", __start___verbose != __stop___verbose));
|
||||
+ assert(("L:no data section value loss", my_var == 3 /* for 2.29.1+ */));
|
||||
+ return *((int *) __start___verbose);
|
||||
+ }]])],
|
||||
+ [gcc_has_attribute_section=yes; cp "conftest${EXEEXT}" "lib_conftest.so"],
|
||||
+ extern int __start___verbose[], __stop___verbose[];
|
||||
+ int test(void) {
|
||||
+ static int my_var __attribute__((section("__verbose"))) = 3;
|
||||
+ assert("L:non-empty data section"
|
||||
+ && __start___verbose != __stop___verbose);
|
||||
+ assert("L:no data section value loss"
|
||||
+ && my_var == 3 /* for 2.29.1+ */);
|
||||
+ return *((int *) __start___verbose); }]]
|
||||
+ )],
|
||||
+ [gcc_has_attribute_section=yes; cp "conftest${EXEEXT}" "conftest.so"],
|
||||
[gcc_has_attribute_section=no]
|
||||
)
|
||||
+ AX_RESTORE_FLAGS
|
||||
@ -258,6 +287,10 @@ index 5601302..6eda2dd 100644
|
||||
-
|
||||
AC_MSG_RESULT($gcc_has_attribute_section)
|
||||
- if test $gcc_has_attribute_section = yes; then
|
||||
- AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1,
|
||||
- [Enabling code using __attribute__((section))])
|
||||
- PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
|
||||
- AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS])
|
||||
+
|
||||
+ # in the failing case (e.g. with ld from binutils 2.29), it's likely the
|
||||
+ # following will fail readily in linkage (hidden symbol `__stop___verbose'
|
||||
@ -271,33 +304,76 @@ index 5601302..6eda2dd 100644
|
||||
+ # but the workaround is still provably needed
|
||||
+ if test "x${gcc_has_attribute_section}" = xyes; then
|
||||
+ AC_MSG_CHECKING([whether linker emits global boundary symbols for orphan sections])
|
||||
+ LIBS="${LIBS} -L. -l_conftest -Wl,-rpath=$(pwd)"
|
||||
+ LIBS="${LIBS} -L. -l:conftest.so -Wl,-rpath=$(pwd)"
|
||||
+ AC_TRY_RUN(
|
||||
+ AC_LANG_PROGRAM(
|
||||
+ [[#include <assert.h>
|
||||
+ extern int __start___verbose[], __stop___verbose[];
|
||||
+ int test(void);]],
|
||||
+ extern int __start___verbose[], __stop___verbose[];
|
||||
+ int test(void);]],
|
||||
+ [[static int my_var __attribute__((section("__verbose"))) = 5;
|
||||
+ assert(("P:non-empty data section", __start___verbose != __stop___verbose));
|
||||
+ assert(("P:no data section value loss", my_var == test() /*5?*/));
|
||||
+ ]]),
|
||||
+ assert("P:non-empty data section"
|
||||
+ && __start___verbose != __stop___verbose);
|
||||
+ assert("P:no data section value loss"
|
||||
+ && my_var == test() /*5?*/);]]
|
||||
+ ),
|
||||
+ [gcc_has_attribute_section_visible=yes],
|
||||
+ [gcc_has_attribute_section_visible=no]
|
||||
+ )
|
||||
+ AX_RESTORE_FLAGS
|
||||
+ AC_MSG_RESULT($gcc_has_attribute_section_visible)
|
||||
+ rm -f "lib_conftest.so"
|
||||
+ rm -f "conftest.so"
|
||||
+
|
||||
AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1,
|
||||
[Enabling code using __attribute__((section))])
|
||||
- PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
|
||||
AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS])
|
||||
+ if test "x${gcc_has_attribute_section_visible}" = xyes; then
|
||||
+ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
|
||||
+ else
|
||||
+ AC_DEFINE([QB_NEED_ATTRIBUTE_SECTION_WORKAROUND], 1,
|
||||
+ if test "x${gcc_has_attribute_section_visible}" = xno; then
|
||||
+ # check if the linker script based workaround is
|
||||
+ # feasible at all, otherwise fallback to using no
|
||||
+ # section attribute while making some noise about it
|
||||
+ # as combining with-without accustomed logging
|
||||
+ # participants is currently uncharted waters
|
||||
+ AC_MSG_CHECKING([whether linker workaround for orphan sections usable])
|
||||
+ >conftest.ld cat <<-EOF
|
||||
+ SECTIONS {
|
||||
+ __verbose : {
|
||||
+ __start___verbose = .;
|
||||
+ *(__verbose);
|
||||
+ __stop___verbose = .;
|
||||
+ }
|
||||
+ }
|
||||
+ EOF
|
||||
+ LDFLAGS="${LDFLAGS} -Wl,conftest.ld"
|
||||
+ AC_LINK_IFELSE(
|
||||
+ [AC_LANG_PROGRAM(
|
||||
+ [[#include <assert.h>
|
||||
+ extern int __start___verbose[], __stop___verbose[];
|
||||
+ int test(void);]],
|
||||
+ [[static int my_var __attribute__((section("__verbose"))) = 5;
|
||||
+ assert("P:non-empty data section"
|
||||
+ && __start___verbose != __stop___verbose);
|
||||
+ assert("P:no data section value loss"
|
||||
+ && my_var == 5);]]
|
||||
+ )],
|
||||
+ [],
|
||||
+ [gcc_has_attribute_section=no]
|
||||
+ )
|
||||
+ AX_RESTORE_FLAGS
|
||||
+ AC_MSG_RESULT([$gcc_has_attribute_section])
|
||||
+ rm -f "conftest.ld"
|
||||
+ fi
|
||||
+
|
||||
+ if test "x${gcc_has_attribute_section}" = xyes; then
|
||||
+ AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1,
|
||||
+ [Enabling code using __attribute__((section))])
|
||||
+ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section-workaround"
|
||||
+ AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS])
|
||||
+ if test "x${gcc_has_attribute_section_visible}" = xyes; then
|
||||
+ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
|
||||
+ else
|
||||
+ AC_DEFINE([QB_NEED_ATTRIBUTE_SECTION_WORKAROUND], 1,
|
||||
+ [Enabling code using __attribute__((section))])
|
||||
+ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section-workaround"
|
||||
+ fi
|
||||
+ elif test "x${enable_nosection_fallback}" = xyes; then
|
||||
+ AC_MSG_NOTICE([Falling back to not using orphan section])
|
||||
+ else
|
||||
+ AC_MSG_ERROR([Would use section attribute, cannot; see --enable-nosection-fallback])
|
||||
+ fi
|
||||
fi
|
||||
fi
|
||||
@ -308,7 +384,7 @@ index 5601302..6eda2dd 100644
|
||||
|
||||
# --- ansi ---
|
||||
if test "x${enable_ansi}" = xyes && \
|
||||
@@ -724,9 +786,11 @@ AC_CONFIG_FILES([Makefile
|
||||
@@ -726,9 +834,11 @@ AC_CONFIG_FILES([Makefile
|
||||
docs/Makefile
|
||||
docs/common.dox
|
||||
docs/html.dox
|
||||
@ -323,7 +399,7 @@ index 5601302..6eda2dd 100644
|
||||
AC_OUTPUT
|
||||
|
||||
diff --git a/lib/Makefile.am b/lib/Makefile.am
|
||||
index 0bebeb5..340cd85 100644
|
||||
index 0bebeb5..ff5b3b4 100644
|
||||
--- a/lib/Makefile.am
|
||||
+++ b/lib/Makefile.am
|
||||
@@ -19,6 +19,7 @@
|
||||
@ -389,7 +465,7 @@ index 0bebeb5..340cd85 100644
|
||||
|
||||
+qblog_script.ld: %.ld: %.ld.in
|
||||
+ $(AM_V_GEN)$(CPP) -xc -I$(top_srcdir)/include -D_GNU_SOURCE -C -P $< \
|
||||
+ | sed -n "/$$(sed -n '/^[^#]/{s/[*\/]/\\\0/g;p;q}' $<)/{:r;p;n;br}" \
|
||||
+ | sed -n "/$$(sed -n '/^[^#]/{s/[*\/]/\\&/g;p;q;}' $<)/,$$ p" \
|
||||
+ > $@
|
||||
+
|
||||
+# find the libqb.so symlink's target, if so, try to find out, iteratively,
|
||||
@ -417,8 +493,24 @@ index 0bebeb5..340cd85 100644
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libqb.pc
|
||||
diff --git a/lib/libqb.pc.in b/lib/libqb.pc.in
|
||||
index 37d27b7..bdcd3c8 100644
|
||||
--- a/lib/libqb.pc.in
|
||||
+++ b/lib/libqb.pc.in
|
||||
@@ -8,5 +8,11 @@ Version: @PACKAGE_VERSION@
|
||||
Description: libqb
|
||||
Requires:
|
||||
Libs: -L${libdir} -lqb @client_dlopen_LIBS@
|
||||
+# NOTE: If -lqb not usable for linking (e.g. linker not compatible with
|
||||
+# linker scripts ad-hoc modifying output sections), try recent
|
||||
+# ld.bfd/binutils linker first when available, otherwise you can
|
||||
+# try "-l:libqb.so.<digit>" link switch (right <digit> available,
|
||||
+# for example, directly within libqb.so plaintext) that bypasses
|
||||
+# said linker script -- but beware, logging problems may ensue.
|
||||
Libs.private: @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
diff --git a/lib/log.c b/lib/log.c
|
||||
index bfd218f..4ed432f 100644
|
||||
index f30b8d8..e4b77d5 100644
|
||||
--- a/lib/log.c
|
||||
+++ b/lib/log.c
|
||||
@@ -40,6 +40,13 @@
|
||||
@ -458,10 +550,10 @@ index 0000000..f262df8
|
||||
+inherited_linker_flags=-Wl,@abs_builddir@/qblog_script.ld
|
||||
diff --git a/lib/qblog_script.ld.in b/lib/qblog_script.ld.in
|
||||
new file mode 100644
|
||||
index 0000000..1f37976
|
||||
index 0000000..fed826b
|
||||
--- /dev/null
|
||||
+++ b/lib/qblog_script.ld.in
|
||||
@@ -0,0 +1,17 @@
|
||||
@@ -0,0 +1,25 @@
|
||||
+#include <qb/qblog.h>
|
||||
+/* GNU ld script
|
||||
+ This atypical arrangement enforces global visibility of boundary symbols
|
||||
@ -469,7 +561,15 @@ index 0000000..1f37976
|
||||
+ QB_ATTR_SECTION used for compile-time offloading of the logging call sites
|
||||
+ tracking. While libqb relies on these being global, default linker from
|
||||
+ binutils change the visibility as of version 2.29, making the logging
|
||||
+ unusable without artificial stimulus: https://bugzilla.redhat.com/1477354 */
|
||||
+ unusable without artificial stimulus: https://bugzilla.redhat.com/1477354
|
||||
+
|
||||
+ NOTE: If -lqb not usable for linking (e.g. linker not compatible with
|
||||
+ linker scripts ad-hoc modifying output sections), try recent
|
||||
+ ld.bfd/binutils linker first when available, otherwise you can
|
||||
+ try "-l:libqb.so.<digit>" link switch (right <digit> available,
|
||||
+ for example, directly within libqb.so plaintext) that bypasses
|
||||
+ said linker script -- but beware, logging problems may ensue.
|
||||
+ */
|
||||
+SECTIONS {
|
||||
+#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
||||
+ QB_ATTR_SECTION : {
|
||||
|
@ -1,4 +1,4 @@
|
||||
From e6833567cd834cbbd182c48327b7e8ce3a8fc2bc Mon Sep 17 00:00:00 2001
|
||||
From d24e62a6b144a0532b1e472744ebbb13aa0221c4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||
Subject: [PATCH 6/6] Low: fix internal object symbol's leak & expose run-time
|
||||
@ -19,19 +19,24 @@ lower-casing applied on originally upper-cased macro identifiers.
|
||||
Better than to roll out a futile data object serving as an artificial
|
||||
anchor for the above purpose, and this was a while due, afterall.
|
||||
|
||||
In turn, also bump "current" and "age" of fields of the libtool's
|
||||
"-version-info" versioning system.
|
||||
|
||||
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||
---
|
||||
include/qb/qbconfig.h.in | 5 ++++-
|
||||
include/qb/qblog.h | 10 ++++++----
|
||||
include/qb/qblog.h | 8 +++++---
|
||||
include/qb/qbutil.h | 11 +++++++++++
|
||||
lib/Makefile.am | 2 +-
|
||||
lib/log.c | 10 ++++++----
|
||||
lib/log_format.c | 2 +-
|
||||
lib/util.c | 7 +++++++
|
||||
tests/functional/log_client.c | 4 ++++
|
||||
tests/functional/log_client.err | 2 +-
|
||||
7 files changed, 34 insertions(+), 7 deletions(-)
|
||||
9 files changed, 40 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/include/qb/qbconfig.h.in b/include/qb/qbconfig.h.in
|
||||
index c1852e1..789fff3 100644
|
||||
index c1852e1..1b92794 100644
|
||||
--- a/include/qb/qbconfig.h.in
|
||||
+++ b/include/qb/qbconfig.h.in
|
||||
@@ -30,7 +30,10 @@
|
||||
@ -40,28 +45,26 @@ index c1852e1..789fff3 100644
|
||||
|
||||
-/* versioning info: MAJOR, MINOR, MICRO, and REST components */
|
||||
+/* versioning info: MAJOR, MINOR, MICRO, and REST components;
|
||||
+ note that static compile-time info is not that useful as run-time
|
||||
+ querying the lower-cased symbolic constants directly from libqb
|
||||
+ note that static compile-time info is not that useful as consulting
|
||||
+ the lower-cased counterparts directly from libqb in run-time
|
||||
+ (see qbutil.h), but that was only introduced after v1.0.2 */
|
||||
#undef QB_VER_MAJOR
|
||||
#undef QB_VER_MINOR
|
||||
#undef QB_VER_MICRO
|
||||
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
|
||||
index e49c86c..7ca236d 100644
|
||||
index 9474c16..56fdd6a 100644
|
||||
--- a/include/qb/qblog.h
|
||||
+++ b/include/qb/qblog.h
|
||||
@@ -279,10 +279,12 @@ extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
||||
#define QB_NONAPI_LOG_INIT_DATA_EXTRA_
|
||||
@@ -293,9 +293,11 @@ extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
||||
#else
|
||||
#define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \
|
||||
- /* libqb sanity (locating libqb by it's relatively unique \
|
||||
#define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \
|
||||
/* libqb sanity (locating libqb by it's relatively unique \
|
||||
- -- and currently only such per-linkage global one -- \
|
||||
- non-functional symbol, due to possible confusion otherwise) */ \
|
||||
- if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli) \
|
||||
+ /* libqb sanity (locating libqb by it's relatively unique \
|
||||
+ non-functional symbol (the two are mutually exclusive, the \
|
||||
+ non-functional symbols -- the two are mutually exclusive, the \
|
||||
+ ordinarily latter was introduced by accident, the former is \
|
||||
+ intentional), due to possible confusion otherwise) */ \
|
||||
+ intentional -- due to possible confusion otherwise) */ \
|
||||
+ if ((dladdr(dlsym(RTLD_DEFAULT, "qb_ver_str"), &work_dli) \
|
||||
+ || dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli)) \
|
||||
&& (work_handle = dlopen(work_dli.dli_fname, \
|
||||
@ -89,6 +92,40 @@ index bfce349..a03bdf8 100644
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
diff --git a/lib/Makefile.am b/lib/Makefile.am
|
||||
index ff5b3b4..a428975 100644
|
||||
--- a/lib/Makefile.am
|
||||
+++ b/lib/Makefile.am
|
||||
@@ -30,7 +30,7 @@ AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
|
||||
lib_LTLIBRARIES = libqb.la
|
||||
|
||||
-libqb_la_LDFLAGS = -version-info 18:2:18
|
||||
+libqb_la_LDFLAGS = -version-info 19:0:19
|
||||
|
||||
source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c \
|
||||
array.c loop.c loop_poll.c loop_job.c \
|
||||
diff --git a/lib/log.c b/lib/log.c
|
||||
index e4b77d5..df5ce5c 100644
|
||||
--- a/lib/log.c
|
||||
+++ b/lib/log.c
|
||||
@@ -892,10 +892,12 @@ qb_log_init(const char *name, int32_t facility, uint8_t priority)
|
||||
#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
||||
/* sanity check that target chain supplied QB_ATTR_SECTION_ST{ART,OP}
|
||||
symbols and hence the local references to them are not referencing
|
||||
- the proper libqb's ones (locating libqb-self by it's relatively
|
||||
- unique -- and currently only such per-linkage global one --
|
||||
- non-functional symbol, due to possible confusion otherwise) */
|
||||
- if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli)
|
||||
+ the proper libqb's ones (locating libqb by it's relatively unique
|
||||
+ non-functional symbols -- the two are mutually exclusive, the
|
||||
+ ordinarily latter was introduced by accident, the former is
|
||||
+ intentional -- due to possible confusion otherwise) */
|
||||
+ if ((dladdr(dlsym(RTLD_DEFAULT, "qb_ver_str"), &work_dli)
|
||||
+ || dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli))
|
||||
&& (work_handle = dlopen(work_dli.dli_fname,
|
||||
RTLD_LOCAL|RTLD_LAZY)) != NULL) {
|
||||
work_s1 = (struct qb_log_callsite *)
|
||||
diff --git a/lib/log_format.c b/lib/log_format.c
|
||||
index 712f447..e7e1f40 100644
|
||||
--- a/lib/log_format.c
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Name: libqb
|
||||
Version: 1.0.2
|
||||
Release: 9%{?dist}
|
||||
Release: 10%{?dist}
|
||||
Summary: An IPC library for high performance servers
|
||||
|
||||
Group: System Environment/Libraries
|
||||
@ -12,7 +12,7 @@ Source0: https://github.com/ClusterLabs/libqb/releases/download/v%{versio
|
||||
Patch0: 01-Med-qblog.h-better-explanation-behaviour-of-QB_LOG_I.patch
|
||||
Patch1: 02-build-configure-run-attribute-section-test-through-r.patch
|
||||
Patch2: 03-tests-new-sort-of-tests-dubbed-functional-cover-link.patch
|
||||
Patch3: 04-Med-add-extra-run-time-client-side-sanity-check-that.patch
|
||||
Patch3: 04-Med-add-extra-run-time-client-libqb-checks-that-logg.patch
|
||||
Patch4: 05-High-bare-fix-for-libqb-logging-not-working-with-ld..patch
|
||||
Patch5: 06-Low-fix-internal-object-symbol-s-leak-expose-run-tim.patch
|
||||
|
||||
@ -77,6 +77,9 @@ developing applications that use %{name}.
|
||||
%{_mandir}/man3/qb*3*
|
||||
|
||||
%changelog
|
||||
* Fri Oct 13 2017 Jan Pokorný <jpokorny+rpm-libqb@redhat.com> - 1.0.2-10
|
||||
- Evolution of the previous (rhbz#1478089, rhbz#1487787)
|
||||
|
||||
* Mon Oct 09 2017 Jan Pokorný <jpokorny+rpm-libqb@redhat.com> - 1.0.2-9
|
||||
- Evolution of the previous (rhbz#1478089, rhbz#1487787)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user