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>
|
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||||
Subject: [PATCH 1/6] Med: qblog.h: better explanation + behaviour of
|
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
|
experience in case that feature does not work well, say because
|
||||||
the linker deliberately changes the previously settled visibility
|
the linker deliberately changes the previously settled visibility
|
||||||
of the section boundary symbols (happened in ld from binutils-2.29,
|
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:
|
- use case:
|
||||||
/usr/sbin/pacemakerd --features
|
/usr/sbin/pacemakerd --features
|
||||||
@ -23,21 +26,59 @@ fix is forthcoming), tweak the assertion message a bit:
|
|||||||
|
|
||||||
- after:
|
- after:
|
||||||
pacemakerd: utils.c:69: common:
|
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
|
Inspired by the suggestion of Ferenc Wágner (for the subsequent
|
||||||
commit, actually).
|
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>
|
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||||
---
|
---
|
||||||
include/qb/qblog.h | 17 ++++++++++++-----
|
include/qb/qblog.h | 34 +++++++++++++++++++++++++++++-----
|
||||||
1 file changed, 12 insertions(+), 5 deletions(-)
|
1 file changed, 29 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
|
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
|
--- a/include/qb/qblog.h
|
||||||
+++ b/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_START[];
|
||||||
extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
||||||
|
|
||||||
@ -46,18 +87,20 @@ index 3cb4eef..d38449d 100644
|
|||||||
- void name(void); \
|
- void name(void); \
|
||||||
- void name(void) \
|
- void name(void) \
|
||||||
- { if (QB_ATTR_SECTION_START == QB_ATTR_SECTION_STOP) assert(0); } \
|
- { if (QB_ATTR_SECTION_START == QB_ATTR_SECTION_STOP) assert(0); } \
|
||||||
+/* optional on-demand self-check of (1) toolchain sanity and (2) non-void
|
+/* optional on-demand self-check of (1) toolchain sanity (prerequisite for
|
||||||
+ * (implied by the justifying existence of at least a single logging callsite
|
+ * the logging subsystem to work properly) and (2) non-void active use of
|
||||||
+ * ~ qb_logt invocation) employment of logging subsystem in the target binary,
|
+ * logging (satisfied with a justifying existence of a logging callsite as
|
||||||
+ * which is presumably assured by it's author as of relying on this macro;
|
+ * 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
|
+ * 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) \
|
+#define QB_LOG_INIT_DATA(name) \
|
||||||
+ void name(void); \
|
+ void name(void); \
|
||||||
+ void name(void) \
|
+ void name(void) \
|
||||||
+ { assert(("non-empty callsite section", \
|
+ { assert("non-empty callsite section" \
|
||||||
+ QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP)); } \
|
+ && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP); } \
|
||||||
void __attribute__ ((constructor)) name(void);
|
void __attribute__ ((constructor)) name(void);
|
||||||
#else
|
#else
|
||||||
#define QB_LOG_INIT_DATA(name)
|
#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>
|
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||||
Subject: [PATCH 2/6] build: configure: run attribute section test through
|
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>
|
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||||
---
|
---
|
||||||
configure.ac | 20 +++++++++++---------
|
configure.ac | 22 +++++++++++++---------
|
||||||
1 file changed, 11 insertions(+), 9 deletions(-)
|
1 file changed, 13 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
diff --git a/configure.ac b/configure.ac
|
||||||
index 22630ba..727b8f0 100644
|
index 22630ba..478194c 100644
|
||||||
--- a/configure.ac
|
--- a/configure.ac
|
||||||
+++ b/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
|
if test "x${GCC}" = xyes; then
|
||||||
AC_MSG_CHECKING([whether GCC supports __attribute__((section()) + ld supports orphan sections])
|
AC_MSG_CHECKING([whether GCC supports __attribute__((section()) + ld supports orphan sections])
|
||||||
if test "x${ac_cv_link_attribute_section}" = x ; then
|
if test "x${ac_cv_link_attribute_section}" = x ; then
|
||||||
@ -40,9 +40,11 @@ index 22630ba..727b8f0 100644
|
|||||||
+ [[#include <assert.h>
|
+ [[#include <assert.h>
|
||||||
+ extern void * __start___verbose, * __stop___verbose;]],
|
+ extern void * __start___verbose, * __stop___verbose;]],
|
||||||
+ [[static int my_var __attribute__((section("__verbose"))) = 5;
|
+ [[static int my_var __attribute__((section("__verbose"))) = 5;
|
||||||
+ assert(("non-empty data section", __start___verbose != __stop___verbose));
|
+ assert("non-empty data section"
|
||||||
+ assert(("no data section value loss", my_var == 5));
|
+ && __start___verbose != __stop___verbose);
|
||||||
+ ]]),
|
+ assert("no data section value loss"
|
||||||
|
+ && my_var == 5);]]
|
||||||
|
+ ),
|
||||||
+ [gcc_has_attribute_section=yes],
|
+ [gcc_has_attribute_section=yes],
|
||||||
+ [gcc_has_attribute_section=no]
|
+ [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>
|
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||||
Subject: [PATCH 3/6] tests: new sort of tests dubbed "functional", cover
|
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
|
confused with regular unit + broader tests). These test are meant to be
|
||||||
compiled on demand only, not during the standard building routine, for
|
compiled on demand only, not during the standard building routine, for
|
||||||
which a trick leveraging GNUmakefile-Makefile precedence with GNU make
|
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
|
The respective new tests are meant to simulate logging variants in two
|
||||||
different library consumption models:
|
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]
|
3. ~ libX(Y) [a.k.a. interlib]
|
||||||
and where "X(Y)" denotes "X linked with linker Y":
|
and where "X(Y)" denotes "X linked with linker Y":
|
||||||
X(a) .. ld.bfd < 2.29
|
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:
|
goes like this:
|
||||||
|
|
||||||
+=========+=========+=========+=========+=========+=========+=========+
|
+=========+=========+=========+=========+=========+=========+=========+
|
||||||
@ -68,6 +70,18 @@ goes like this:
|
|||||||
# x = b # BAD[*A] | BAD[*B] : BAD[*C] # BAD[*1] | BAD[*C] : BAD[*3] #
|
# 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
|
[*1] client logging not working
|
||||||
[*2] interlib logging not working
|
[*2] interlib logging not working
|
||||||
[*3] both client and 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,
|
[*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
|
which makes it boil down just to [*1] (hypothesis: mere internal
|
||||||
self-reference to the section's boundary symbols makes them
|
self-reference to the section's boundary symbols makes them
|
||||||
overcome some kind of garbage collection at the linkage stage,
|
overcome some kind of symbol garbage collection at the linkage
|
||||||
so they are exposed even they wouldn't be otherwise as demonstrated
|
stage, so they are exposed even they wouldn't be otherwise as
|
||||||
with the initial, plain case of [*3])
|
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
|
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
|
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
|
availability of a working logging doesn't depend solely on the linkers
|
||||||
in question, but generally (further investigation out of scope) the
|
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 logging-related discrete compilation units, also (self-)referencing
|
||||||
of the section's boundary denoting symbols is a deciding factor whether
|
of the section's boundary denoting symbols is a deciding factor whether
|
||||||
particular logging source will be honored. This may be a result of
|
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.c | 64 ++++++
|
||||||
tests/functional/log_interlib_client.err | 4 +
|
tests/functional/log_interlib_client.err | 4 +
|
||||||
tests/functional/log_internal/Makefile.am | 23 +++
|
tests/functional/log_internal/Makefile.am | 23 +++
|
||||||
tests/functional/log_test_client.sh | 22 +++
|
tests/functional/log_test_client.sh | 22 ++
|
||||||
tests/functional/log_test_interlib_client.sh | 22 +++
|
tests/functional/log_test_interlib_client.sh | 22 ++
|
||||||
tests/functional/log_test_mock.sh | 285 +++++++++++++++++++++++++++
|
tests/functional/log_test_mock.sh | 289 +++++++++++++++++++++++++++
|
||||||
18 files changed, 704 insertions(+), 2 deletions(-)
|
16 files changed, 706 insertions(+), 2 deletions(-)
|
||||||
create mode 100644 tests/functional/GNUmakefile
|
create mode 100644 tests/functional/GNUmakefile
|
||||||
create mode 100644 tests/functional/Makefile.am
|
create mode 100644 tests/functional/Makefile.am
|
||||||
create mode 100644 tests/functional/log.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
|
create mode 100755 tests/functional/log_test_mock.sh
|
||||||
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
diff --git a/configure.ac b/configure.ac
|
||||||
index 727b8f0..db7bc68 100644
|
index 478194c..274b49c 100644
|
||||||
--- a/configure.ac
|
--- a/configure.ac
|
||||||
+++ b/configure.ac
|
+++ b/configure.ac
|
||||||
@@ -13,7 +13,7 @@ AC_CONFIG_SRCDIR([lib/ringbuffer.c])
|
@@ -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 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 normal compilation. When a failure occurs, it will then display the full
|
||||||
dnl command line
|
dnl command line
|
||||||
@@ -715,6 +715,9 @@ AC_CONFIG_FILES([Makefile
|
@@ -717,6 +717,9 @@ AC_CONFIG_FILES([Makefile
|
||||||
lib/libqb.pc
|
lib/libqb.pc
|
||||||
tools/Makefile
|
tools/Makefile
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
@ -155,7 +183,7 @@ index 727b8f0..db7bc68 100644
|
|||||||
tests/test.conf
|
tests/test.conf
|
||||||
examples/Makefile
|
examples/Makefile
|
||||||
docs/Makefile
|
docs/Makefile
|
||||||
@@ -722,6 +725,8 @@ AC_CONFIG_FILES([Makefile
|
@@ -724,6 +727,8 @@ AC_CONFIG_FILES([Makefile
|
||||||
docs/html.dox
|
docs/html.dox
|
||||||
docs/man.dox])
|
docs/man.dox])
|
||||||
|
|
||||||
@ -672,10 +700,10 @@ index 0000000..59c5555
|
|||||||
+diff -u ../log_interlib_client.err log_interlib_client.err.real
|
+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
|
diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh
|
||||||
new file mode 100755
|
new file mode 100755
|
||||||
index 0000000..fb2c02c
|
index 0000000..4489718
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/tests/functional/log_test_mock.sh
|
+++ b/tests/functional/log_test_mock.sh
|
||||||
@@ -0,0 +1,285 @@
|
@@ -0,0 +1,289 @@
|
||||||
+#!/bin/sh
|
+#!/bin/sh
|
||||||
+# Copyright 2017 Red Hat, Inc.
|
+# Copyright 2017 Red Hat, Inc.
|
||||||
+#
|
+#
|
||||||
@ -736,6 +764,7 @@ index 0000000..fb2c02c
|
|||||||
+mock_args="-r fedora-27-${arch}"
|
+mock_args="-r fedora-27-${arch}"
|
||||||
+pkg_binutils_228=binutils-2.28-14.fc27
|
+pkg_binutils_228=binutils-2.28-14.fc27
|
||||||
+pkg_binutils_229=binutils-2.29-6.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
|
+# prettified reporters
|
||||||
@ -875,7 +904,7 @@ index 0000000..fb2c02c
|
|||||||
+ | sed -n '/\.tar/{s|\.tar\.[^.]*$||;p;q}')"
|
+ | sed -n '/\.tar/{s|\.tar\.[^.]*$||;p;q}')"
|
||||||
+
|
+
|
||||||
+ _resultsdir="_results/$(date '+%y%m%d_%H%M%S')_${_libqb_descriptor}"
|
+ _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}"
|
+ mkdir -p "${_resultsdir}"
|
||||||
+ rm -f -- "${_resultsdir}/*"
|
+ rm -f -- "${_resultsdir}/*"
|
||||||
+
|
+
|
||||||
@ -895,16 +924,19 @@ index 0000000..fb2c02c
|
|||||||
+ esac
|
+ esac
|
||||||
+
|
+
|
||||||
+ do_progress "installing ${_pkg_binutils_libqb} so as to build" \
|
+ do_progress "installing ${_pkg_binutils_libqb} so as to build" \
|
||||||
+ " libqb [${_outfile_qb}]"
|
+ "libqb [${_outfile_qb}]"
|
||||||
+ do_install "${_pkg_binutils_libqb}"
|
+ do_install "${_pkg_binutils_libqb}"
|
||||||
+
|
+
|
||||||
+ do_progress "building ${_libqb_descriptor_path} with" \
|
+ do_progress "building ${_libqb_descriptor_path} with" \
|
||||||
+ " ${_pkg_binutils_libqb} [${_outfile_qb}]"
|
+ "${_pkg_binutils_libqb} [${_outfile_qb}]"
|
||||||
+ do_buildsrpm "${_libqb_descriptor_path}" "${_dist}"
|
+ do_buildsrpm "${_libqb_descriptor_path}" "${_dist}"
|
||||||
+
|
+
|
||||||
+ do_progress "installing ${_libqb_descriptor}-based packages" \
|
+ 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}"
|
+ 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
|
+ for _pkg_binutils_interlib in none "${pkg_binutils_228}" "${pkg_binutils_229}"; do
|
||||||
+
|
+
|
||||||
@ -919,11 +951,11 @@ index 0000000..fb2c02c
|
|||||||
+ none) ;;
|
+ none) ;;
|
||||||
+ *)
|
+ *)
|
||||||
+ do_progress "installing ${_pkg_binutils_interlib}" \
|
+ do_progress "installing ${_pkg_binutils_interlib}" \
|
||||||
+ " so as to build interlib [${_outfile}]"
|
+ "so as to build interlib [${_outfile}]"
|
||||||
+ do_install "${_pkg_binutils_interlib}"
|
+ do_install "${_pkg_binutils_interlib}"
|
||||||
+
|
+
|
||||||
+ do_progress "building interlib with ${_libqb_descriptor_archive}" \
|
+ do_progress "building interlib with ${_libqb_descriptor_archive}" \
|
||||||
+ " + ${_pkg_binutils_interlib} [${_outfile}]"
|
+ "+ ${_pkg_binutils_interlib} [${_outfile}]"
|
||||||
+ do_compile_interlib "${_libqb_descriptor_archive}" "${_makevars}"
|
+ do_compile_interlib "${_libqb_descriptor_archive}" "${_makevars}"
|
||||||
+ ;;
|
+ ;;
|
||||||
+ esac
|
+ esac
|
||||||
@ -940,10 +972,10 @@ index 0000000..fb2c02c
|
|||||||
+ esac
|
+ esac
|
||||||
+
|
+
|
||||||
+ do_progress "installing ${_pkg_binutils_client}" \
|
+ 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_install "${_pkg_binutils_client}"
|
||||||
+ do_progress "building ${_client} with ${_libqb_descriptor_archive}" \
|
+ 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}" \
|
+ do_compile_and_test_client "${_libqb_descriptor_archive}" \
|
||||||
+ "${_client}" "${_resultsdir}" \
|
+ "${_client}" "${_resultsdir}" \
|
||||||
+ "${_outfile_client}" "${_makevars}"
|
+ "${_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>
|
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||||
Subject: [PATCH 5/6] High: bare fix for libqb logging not working with
|
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
|
And then for 2.29.1 release of binutils once again, as someone actually
|
||||||
noticed something went overboard with the 2.29 changes:
|
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
|
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
|
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
|
libqb_la_LIBADD, and with a little bit of further fiddling, it works
|
||||||
as desired (note that double occurrence of "-Wl,foo.t" equivalent
|
as desired (note that double occurrence of "-Wl,foo.t" equivalent
|
||||||
present at some stages of sorting this trick turned out to be,
|
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
|
NOTE: some forms of libtool distribution (debian + derivatives ones
|
||||||
in particular) undermine natural transitive dependency propagation
|
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
|
of consuming libqb outside of it's own playground is hardly
|
||||||
the Right Thing) if portability is important, nonetheless!
|
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
|
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,
|
"-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
|
under all circumstances, which is already achieved with the arrangement
|
||||||
experiments, further redefinition of those boundary denoting symbols
|
for b. above, and by experiments, further redefinition of those boundary
|
||||||
as weak was necessary so as to make them truly global within libqb.so
|
denoting symbols as weak was necessary so as to make them truly global
|
||||||
proper (at least with binutils 2.29).
|
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,
|
overview changes as of this commit, but first as a recap,
|
||||||
"X(Y)" denotes "X linked with linker Y":
|
"X(Y)" denotes "X linked with linker Y":
|
||||||
X(a) .. ld.bfd < 2.29
|
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
|
and here you are (values in <angle brackets> denote non-trivial change
|
||||||
[not mere rewording] introduced as of this commit, in comparison to the
|
[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>
|
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||||
---
|
---
|
||||||
configure.ac | 90 +++++++++++++++++++++++++++++++++++++++++-------
|
configure.ac | 146 +++++++++++++++++++++++++++++++++++++++++------
|
||||||
lib/Makefile.am | 67 +++++++++++++++++++++++++++++++++++
|
lib/Makefile.am | 67 ++++++++++++++++++++++
|
||||||
lib/log.c | 7 ++++
|
lib/libqb.pc.in | 6 ++
|
||||||
lib/qblog_script.la.in | 15 ++++++++
|
lib/log.c | 7 +++
|
||||||
lib/qblog_script.ld.in | 17 +++++++++
|
lib/qblog_script.la.in | 15 +++++
|
||||||
lib/qblog_script_noop.ld | 1 +
|
lib/qblog_script.ld.in | 25 ++++++++
|
||||||
7 files changed, 184 insertions(+), 13 deletions(-)
|
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.la.in
|
||||||
create mode 100644 lib/qblog_script.ld.in
|
create mode 100644 lib/qblog_script.ld.in
|
||||||
create mode 100644 lib/qblog_script_noop.ld
|
create mode 100644 lib/qblog_script_noop.ld
|
||||||
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
diff --git a/configure.ac b/configure.ac
|
||||||
index 5601302..6eda2dd 100644
|
index 5769e60..57875c8 100644
|
||||||
--- a/configure.ac
|
--- a/configure.ac
|
||||||
+++ b/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],
|
AC_ARG_ENABLE([coverage],
|
||||||
[AS_HELP_STRING([--enable-coverage],[coverage analysis of the codebase])])
|
[AS_HELP_STRING([--enable-coverage],[coverage analysis of the codebase])])
|
||||||
|
|
||||||
+AC_ARG_ENABLE([interlib-deps],
|
+AC_ARG_ENABLE([interlib-deps],
|
||||||
+ [AS_HELP_STRING([--disable-interlib-deps],
|
+ [AS_HELP_STRING([--disable-interlib-deps],
|
||||||
+ [disable inter-library dependencies (might break builds)])],
|
+ [disable inter-library dependencies (might break builds)])])
|
||||||
+ [enable_interlib_deps="$enableval"],
|
+
|
||||||
+ [enable_interlib_deps="yes"])
|
+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],
|
AC_ARG_ENABLE([slow-tests],
|
||||||
[AS_HELP_STRING([--enable-slow-tests],[build and run 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=""
|
COVERAGE_LDFLAGS=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -212,17 +237,17 @@ index 5601302..6eda2dd 100644
|
|||||||
+# override the libtool variable by force because the current
|
+# override the libtool variable by force because the current
|
||||||
+# arrangement relies on transitive dependency propagation
|
+# arrangement relies on transitive dependency propagation
|
||||||
+AC_MSG_NOTICE([Enabling inter-library dependencies: $enable_interlib_deps])
|
+AC_MSG_NOTICE([Enabling inter-library dependencies: $enable_interlib_deps])
|
||||||
+if test "${enable_interlib_deps}" == "yes"; then
|
+if test "x${enable_interlib_deps}" = xno; then
|
||||||
+ link_all_deplibs=yes
|
|
||||||
+else
|
|
||||||
+ link_all_deplibs=no
|
+ link_all_deplibs=no
|
||||||
|
+else
|
||||||
|
+ link_all_deplibs=yes
|
||||||
+fi
|
+fi
|
||||||
+
|
+
|
||||||
+# --- slow tests ---
|
+# --- slow tests ---
|
||||||
if test "x${enable_slow_tests}" = xyes ; then
|
if test "x${enable_slow_tests}" = xyes ; then
|
||||||
AC_DEFINE([HAVE_SLOW_TESTS], 1,[have slow tests])
|
AC_DEFINE([HAVE_SLOW_TESTS], 1,[have slow tests])
|
||||||
AC_MSG_NOTICE([Enabling 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 ---
|
# --- callsite sections ---
|
||||||
if test "x${GCC}" = xyes; then
|
if test "x${GCC}" = xyes; then
|
||||||
@ -237,18 +262,22 @@ index 5601302..6eda2dd 100644
|
|||||||
[[#include <assert.h>
|
[[#include <assert.h>
|
||||||
- extern void * __start___verbose, * __stop___verbose;]],
|
- extern void * __start___verbose, * __stop___verbose;]],
|
||||||
- [[static int my_var __attribute__((section("__verbose"))) = 5;
|
- [[static int my_var __attribute__((section("__verbose"))) = 5;
|
||||||
- assert(("non-empty data section", __start___verbose != __stop___verbose));
|
- assert("non-empty data section"
|
||||||
- assert(("no data section value loss", my_var == 5));
|
- && __start___verbose != __stop___verbose);
|
||||||
- ]]),
|
- assert("no data section value loss"
|
||||||
|
- && my_var == 5);]]
|
||||||
|
- ),
|
||||||
- [gcc_has_attribute_section=yes],
|
- [gcc_has_attribute_section=yes],
|
||||||
+ extern int __start___verbose[], __stop___verbose[];
|
+ extern int __start___verbose[], __stop___verbose[];
|
||||||
+ int test(void) {
|
+ int test(void) {
|
||||||
+ static int my_var __attribute__((section("__verbose"))) = 3;
|
+ static int my_var __attribute__((section("__verbose"))) = 3;
|
||||||
+ assert(("L:non-empty data section", __start___verbose != __stop___verbose));
|
+ assert("L:non-empty data section"
|
||||||
+ assert(("L:no data section value loss", my_var == 3 /* for 2.29.1+ */));
|
+ && __start___verbose != __stop___verbose);
|
||||||
+ return *((int *) __start___verbose);
|
+ assert("L:no data section value loss"
|
||||||
+ }]])],
|
+ && my_var == 3 /* for 2.29.1+ */);
|
||||||
+ [gcc_has_attribute_section=yes; cp "conftest${EXEEXT}" "lib_conftest.so"],
|
+ return *((int *) __start___verbose); }]]
|
||||||
|
+ )],
|
||||||
|
+ [gcc_has_attribute_section=yes; cp "conftest${EXEEXT}" "conftest.so"],
|
||||||
[gcc_has_attribute_section=no]
|
[gcc_has_attribute_section=no]
|
||||||
)
|
)
|
||||||
+ AX_RESTORE_FLAGS
|
+ AX_RESTORE_FLAGS
|
||||||
@ -258,6 +287,10 @@ index 5601302..6eda2dd 100644
|
|||||||
-
|
-
|
||||||
AC_MSG_RESULT($gcc_has_attribute_section)
|
AC_MSG_RESULT($gcc_has_attribute_section)
|
||||||
- if test $gcc_has_attribute_section = yes; then
|
- 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
|
+ # 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'
|
+ # 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
|
+ # but the workaround is still provably needed
|
||||||
+ if test "x${gcc_has_attribute_section}" = xyes; then
|
+ if test "x${gcc_has_attribute_section}" = xyes; then
|
||||||
+ AC_MSG_CHECKING([whether linker emits global boundary symbols for orphan sections])
|
+ 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_TRY_RUN(
|
||||||
+ AC_LANG_PROGRAM(
|
+ AC_LANG_PROGRAM(
|
||||||
+ [[#include <assert.h>
|
+ [[#include <assert.h>
|
||||||
+ extern int __start___verbose[], __stop___verbose[];
|
+ extern int __start___verbose[], __stop___verbose[];
|
||||||
+ int test(void);]],
|
+ int test(void);]],
|
||||||
+ [[static int my_var __attribute__((section("__verbose"))) = 5;
|
+ [[static int my_var __attribute__((section("__verbose"))) = 5;
|
||||||
+ assert(("P:non-empty data section", __start___verbose != __stop___verbose));
|
+ assert("P:non-empty data section"
|
||||||
+ assert(("P:no data section value loss", my_var == test() /*5?*/));
|
+ && __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=yes],
|
||||||
+ [gcc_has_attribute_section_visible=no]
|
+ [gcc_has_attribute_section_visible=no]
|
||||||
+ )
|
+ )
|
||||||
+ AX_RESTORE_FLAGS
|
+ AX_RESTORE_FLAGS
|
||||||
+ AC_MSG_RESULT($gcc_has_attribute_section_visible)
|
+ AC_MSG_RESULT($gcc_has_attribute_section_visible)
|
||||||
+ rm -f "lib_conftest.so"
|
+ rm -f "conftest.so"
|
||||||
+
|
+
|
||||||
AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1,
|
+ if test "x${gcc_has_attribute_section_visible}" = xno; then
|
||||||
[Enabling code using __attribute__((section))])
|
+ # check if the linker script based workaround is
|
||||||
- PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
|
+ # feasible at all, otherwise fallback to using no
|
||||||
AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS])
|
+ # section attribute while making some noise about it
|
||||||
+ if test "x${gcc_has_attribute_section_visible}" = xyes; then
|
+ # as combining with-without accustomed logging
|
||||||
+ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
|
+ # participants is currently uncharted waters
|
||||||
+ else
|
+ AC_MSG_CHECKING([whether linker workaround for orphan sections usable])
|
||||||
+ AC_DEFINE([QB_NEED_ATTRIBUTE_SECTION_WORKAROUND], 1,
|
+ >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))])
|
+ [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
|
fi
|
||||||
fi
|
fi
|
||||||
@ -308,7 +384,7 @@ index 5601302..6eda2dd 100644
|
|||||||
|
|
||||||
# --- ansi ---
|
# --- ansi ---
|
||||||
if test "x${enable_ansi}" = xyes && \
|
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/Makefile
|
||||||
docs/common.dox
|
docs/common.dox
|
||||||
docs/html.dox
|
docs/html.dox
|
||||||
@ -323,7 +399,7 @@ index 5601302..6eda2dd 100644
|
|||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
diff --git a/lib/Makefile.am b/lib/Makefile.am
|
diff --git a/lib/Makefile.am b/lib/Makefile.am
|
||||||
index 0bebeb5..340cd85 100644
|
index 0bebeb5..ff5b3b4 100644
|
||||||
--- a/lib/Makefile.am
|
--- a/lib/Makefile.am
|
||||||
+++ b/lib/Makefile.am
|
+++ b/lib/Makefile.am
|
||||||
@@ -19,6 +19,7 @@
|
@@ -19,6 +19,7 @@
|
||||||
@ -389,7 +465,7 @@ index 0bebeb5..340cd85 100644
|
|||||||
|
|
||||||
+qblog_script.ld: %.ld: %.ld.in
|
+qblog_script.ld: %.ld: %.ld.in
|
||||||
+ $(AM_V_GEN)$(CPP) -xc -I$(top_srcdir)/include -D_GNU_SOURCE -C -P $< \
|
+ $(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,
|
+# 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
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = libqb.pc
|
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
|
diff --git a/lib/log.c b/lib/log.c
|
||||||
index bfd218f..4ed432f 100644
|
index f30b8d8..e4b77d5 100644
|
||||||
--- a/lib/log.c
|
--- a/lib/log.c
|
||||||
+++ b/lib/log.c
|
+++ b/lib/log.c
|
||||||
@@ -40,6 +40,13 @@
|
@@ -40,6 +40,13 @@
|
||||||
@ -458,10 +550,10 @@ index 0000000..f262df8
|
|||||||
+inherited_linker_flags=-Wl,@abs_builddir@/qblog_script.ld
|
+inherited_linker_flags=-Wl,@abs_builddir@/qblog_script.ld
|
||||||
diff --git a/lib/qblog_script.ld.in b/lib/qblog_script.ld.in
|
diff --git a/lib/qblog_script.ld.in b/lib/qblog_script.ld.in
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..1f37976
|
index 0000000..fed826b
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/lib/qblog_script.ld.in
|
+++ b/lib/qblog_script.ld.in
|
||||||
@@ -0,0 +1,17 @@
|
@@ -0,0 +1,25 @@
|
||||||
+#include <qb/qblog.h>
|
+#include <qb/qblog.h>
|
||||||
+/* GNU ld script
|
+/* GNU ld script
|
||||||
+ This atypical arrangement enforces global visibility of boundary symbols
|
+ 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
|
+ QB_ATTR_SECTION used for compile-time offloading of the logging call sites
|
||||||
+ tracking. While libqb relies on these being global, default linker from
|
+ tracking. While libqb relies on these being global, default linker from
|
||||||
+ binutils change the visibility as of version 2.29, making the logging
|
+ 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 {
|
+SECTIONS {
|
||||||
+#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
+#ifdef QB_HAVE_ATTRIBUTE_SECTION
|
||||||
+ QB_ATTR_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>
|
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
|
||||||
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
Date: Fri, 6 Oct 2017 17:17:26 +0200
|
||||||
Subject: [PATCH 6/6] Low: fix internal object symbol's leak & expose run-time
|
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
|
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.
|
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>
|
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
|
||||||
---
|
---
|
||||||
include/qb/qbconfig.h.in | 5 ++++-
|
include/qb/qbconfig.h.in | 5 ++++-
|
||||||
include/qb/qblog.h | 10 ++++++----
|
include/qb/qblog.h | 8 +++++---
|
||||||
include/qb/qbutil.h | 11 +++++++++++
|
include/qb/qbutil.h | 11 +++++++++++
|
||||||
|
lib/Makefile.am | 2 +-
|
||||||
|
lib/log.c | 10 ++++++----
|
||||||
lib/log_format.c | 2 +-
|
lib/log_format.c | 2 +-
|
||||||
lib/util.c | 7 +++++++
|
lib/util.c | 7 +++++++
|
||||||
tests/functional/log_client.c | 4 ++++
|
tests/functional/log_client.c | 4 ++++
|
||||||
tests/functional/log_client.err | 2 +-
|
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
|
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
|
--- a/include/qb/qbconfig.h.in
|
||||||
+++ b/include/qb/qbconfig.h.in
|
+++ b/include/qb/qbconfig.h.in
|
||||||
@@ -30,7 +30,10 @@
|
@@ -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 */
|
||||||
+/* 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
|
+ note that static compile-time info is not that useful as consulting
|
||||||
+ querying the lower-cased symbolic constants directly from libqb
|
+ the lower-cased counterparts directly from libqb in run-time
|
||||||
+ (see qbutil.h), but that was only introduced after v1.0.2 */
|
+ (see qbutil.h), but that was only introduced after v1.0.2 */
|
||||||
#undef QB_VER_MAJOR
|
#undef QB_VER_MAJOR
|
||||||
#undef QB_VER_MINOR
|
#undef QB_VER_MINOR
|
||||||
#undef QB_VER_MICRO
|
#undef QB_VER_MICRO
|
||||||
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
|
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
|
--- a/include/qb/qblog.h
|
||||||
+++ b/include/qb/qblog.h
|
+++ b/include/qb/qblog.h
|
||||||
@@ -279,10 +279,12 @@ extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
@@ -293,9 +293,11 @@ extern struct qb_log_callsite QB_ATTR_SECTION_STOP[];
|
||||||
#define QB_NONAPI_LOG_INIT_DATA_EXTRA_
|
|
||||||
#else
|
#else
|
||||||
#define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \
|
#define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \
|
||||||
- /* libqb sanity (locating libqb by it's relatively unique \
|
/* libqb sanity (locating libqb by it's relatively unique \
|
||||||
- -- and currently only such per-linkage global one -- \
|
- -- and currently only such per-linkage global one -- \
|
||||||
- non-functional symbol, due to possible confusion otherwise) */ \
|
- non-functional symbol, due to possible confusion otherwise) */ \
|
||||||
- if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli) \
|
- if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli) \
|
||||||
+ /* libqb sanity (locating libqb by it's relatively unique \
|
+ non-functional symbols -- the two are mutually exclusive, the \
|
||||||
+ non-functional symbol (the two are mutually exclusive, the \
|
|
||||||
+ ordinarily latter was introduced by accident, the former is \
|
+ 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) \
|
+ if ((dladdr(dlsym(RTLD_DEFAULT, "qb_ver_str"), &work_dli) \
|
||||||
+ || dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli)) \
|
+ || dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli)) \
|
||||||
&& (work_handle = dlopen(work_dli.dli_fname, \
|
&& (work_handle = dlopen(work_dli.dli_fname, \
|
||||||
@ -89,6 +92,40 @@ index bfce349..a03bdf8 100644
|
|||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
#ifdef __cplusplus
|
#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
|
diff --git a/lib/log_format.c b/lib/log_format.c
|
||||||
index 712f447..e7e1f40 100644
|
index 712f447..e7e1f40 100644
|
||||||
--- a/lib/log_format.c
|
--- a/lib/log_format.c
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Name: libqb
|
Name: libqb
|
||||||
Version: 1.0.2
|
Version: 1.0.2
|
||||||
Release: 9%{?dist}
|
Release: 10%{?dist}
|
||||||
Summary: An IPC library for high performance servers
|
Summary: An IPC library for high performance servers
|
||||||
|
|
||||||
Group: System Environment/Libraries
|
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
|
Patch0: 01-Med-qblog.h-better-explanation-behaviour-of-QB_LOG_I.patch
|
||||||
Patch1: 02-build-configure-run-attribute-section-test-through-r.patch
|
Patch1: 02-build-configure-run-attribute-section-test-through-r.patch
|
||||||
Patch2: 03-tests-new-sort-of-tests-dubbed-functional-cover-link.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
|
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
|
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*
|
%{_mandir}/man3/qb*3*
|
||||||
|
|
||||||
%changelog
|
%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
|
* Mon Oct 09 2017 Jan Pokorný <jpokorny+rpm-libqb@redhat.com> - 1.0.2-9
|
||||||
- Evolution of the previous (rhbz#1478089, rhbz#1487787)
|
- Evolution of the previous (rhbz#1478089, rhbz#1487787)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user