diff --git a/01-Med-qblog.h-better-explanation-behaviour-of-QB_LOG_I.patch b/01-Med-qblog.h-better-explanation-behaviour-of-QB_LOG_I.patch index 41e7765..70223d8 100644 --- a/01-Med-qblog.h-better-explanation-behaviour-of-QB_LOG_I.patch +++ b/01-Med-qblog.h-better-explanation-behaviour-of-QB_LOG_I.patch @@ -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?= Date: Fri, 6 Oct 2017 17:17:26 +0200 Subject: [PATCH 1/6] Med: qblog.h: better explanation + behaviour of @@ -12,7 +12,10 @@ put a better description for the macro. Also based on poor user experience in case that feature does not work well, say because the linker deliberately changes the previously settled visibility of the section boundary symbols (happened in ld from binutils-2.29, -fix is forthcoming), tweak the assertion message a bit: +fix is forthcoming), tweak the assertion message a bit, together +with an extension of the general intro to point that macro out. +Also play fair, include the header, which this macro +requires. - use case: /usr/sbin/pacemakerd --features @@ -23,21 +26,59 @@ fix is forthcoming), tweak the assertion message a bit: - after: pacemakerd: utils.c:69: common: - Assertion `("non-empty callsite section", QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP)' failed. + Assertion `"non-empty callsite section" && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP' failed. Inspired by the suggestion of Ferenc Wágner (for the subsequent commit, actually). +And regarding: +> as a side effect, it can ensure the boundary-denoting symbols for +> the target collection area are kept alive with some otherwise unkind +> linkers +this was actually empirically discovered in one particular combination +with ld.bfd @ binutils 2.29, and extensively with 2.29.1 (placing here +a forward reference for the following commits that elaborate on the +libqb-target cross-combination matrix and the findings). + Signed-off-by: Jan Pokorný --- - include/qb/qblog.h | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) + include/qb/qblog.h | 34 +++++++++++++++++++++++++++++----- + 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/include/qb/qblog.h b/include/qb/qblog.h -index 3cb4eef..d38449d 100644 +index 3cb4eef..d39803f 100644 --- a/include/qb/qblog.h +++ b/include/qb/qblog.h -@@ -268,11 +268,18 @@ typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs); +@@ -42,6 +42,10 @@ extern "C" { + #undef QB_HAVE_ATTRIBUTE_SECTION + #endif /* S_SPLINT_S */ + ++#ifdef QB_HAVE_ATTRIBUTE_SECTION ++#include /* possibly needed for QB_LOG_INIT_DATA */ ++#endif ++ + /** + * @file qblog.h + * The logging API provides four main parts (basics, filtering, threading & blackbox). +@@ -64,6 +68,17 @@ extern "C" { + * } + * @endcode + * ++ * @note ++ * In practice, such a minimalistic approach hardly caters real use cases. ++ * Following section discusses the customization. Moreover, it's quite ++ * vital to instrument the target user of this logging subsystem with ++ * @c QB_LOG_INIT_DATA() macro placed in the top file scope in an exactly ++ * one source file (preferably the main one) to be compiled into the ++ * resulting binary. This is a self-defensive measure for when the ++ * linker-assisted collection of callsite data silently fails, which ++ * could otherwise go unnoticed, causing troubles down the road. ++ * ++ * + * @par Configuring log targets. + * A log target can be syslog, stderr, the blackbox, stdout, or a text file. + * By default only syslog is enabled. +@@ -268,11 +283,20 @@ typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs); extern struct qb_log_callsite QB_ATTR_SECTION_START[]; extern struct qb_log_callsite QB_ATTR_SECTION_STOP[]; @@ -46,18 +87,20 @@ index 3cb4eef..d38449d 100644 - void name(void); \ - void name(void) \ - { if (QB_ATTR_SECTION_START == QB_ATTR_SECTION_STOP) assert(0); } \ -+/* optional on-demand self-check of (1) toolchain sanity and (2) non-void -+ * (implied by the justifying existence of at least a single logging callsite -+ * ~ qb_logt invocation) employment of logging subsystem in the target binary, -+ * which is presumably assured by it's author as of relying on this macro; ++/* optional on-demand self-check of (1) toolchain sanity (prerequisite for ++ * the logging subsystem to work properly) and (2) non-void active use of ++ * logging (satisfied with a justifying existence of a logging callsite as ++ * defined with a @c qb_logt invocation) at the target binary, which is ++ * presumably assured by it's author as of relying on this very macro; + * only effective when link-time ("run-time amortizing") callsite collection -+ * is available and may be extended in future for more in-depth self-validation -+ */ ++ * is; as a side effect, it can ensure the boundary-denoting symbols for the ++ * target collection area are kept alive with some otherwise unkind linkers; ++ * may be extended in future for more in-depth self-validation */ +#define QB_LOG_INIT_DATA(name) \ + void name(void); \ + void name(void) \ -+ { assert(("non-empty callsite section", \ -+ QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP)); } \ ++ { assert("non-empty callsite section" \ ++ && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP); } \ void __attribute__ ((constructor)) name(void); #else #define QB_LOG_INIT_DATA(name) diff --git a/02-build-configure-run-attribute-section-test-through-r.patch b/02-build-configure-run-attribute-section-test-through-r.patch index 0c276f7..c6a4aa8 100644 --- a/02-build-configure-run-attribute-section-test-through-r.patch +++ b/02-build-configure-run-attribute-section-test-through-r.patch @@ -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?= Date: Fri, 6 Oct 2017 17:17:26 +0200 Subject: [PATCH 2/6] build: configure: run attribute section test through @@ -15,14 +15,14 @@ of the run-time error signalling through assertions. Signed-off-by: Jan Pokorný --- - configure.ac | 20 +++++++++++--------- - 1 file changed, 11 insertions(+), 9 deletions(-) + configure.ac | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac -index 22630ba..727b8f0 100644 +index 22630ba..478194c 100644 --- a/configure.ac +++ b/configure.ac -@@ -620,15 +620,17 @@ AC_SUBST(HAVE_SLOW_TESTS) +@@ -620,15 +620,19 @@ AC_SUBST(HAVE_SLOW_TESTS) if test "x${GCC}" = xyes; then AC_MSG_CHECKING([whether GCC supports __attribute__((section()) + ld supports orphan sections]) if test "x${ac_cv_link_attribute_section}" = x ; then @@ -40,9 +40,11 @@ index 22630ba..727b8f0 100644 + [[#include + extern void * __start___verbose, * __stop___verbose;]], + [[static int my_var __attribute__((section("__verbose"))) = 5; -+ assert(("non-empty data section", __start___verbose != __stop___verbose)); -+ assert(("no data section value loss", my_var == 5)); -+ ]]), ++ assert("non-empty data section" ++ && __start___verbose != __stop___verbose); ++ assert("no data section value loss" ++ && my_var == 5);]] ++ ), + [gcc_has_attribute_section=yes], + [gcc_has_attribute_section=no] + ) diff --git a/03-tests-new-sort-of-tests-dubbed-functional-cover-link.patch b/03-tests-new-sort-of-tests-dubbed-functional-cover-link.patch index 577961b..efafe90 100644 --- a/03-tests-new-sort-of-tests-dubbed-functional-cover-link.patch +++ b/03-tests-new-sort-of-tests-dubbed-functional-cover-link.patch @@ -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?= Date: Fri, 6 Oct 2017 17:17:26 +0200 Subject: [PATCH 3/6] tests: new sort of tests dubbed "functional", cover @@ -14,7 +14,9 @@ checking harness, usually available through "make check", but not to be confused with regular unit + broader tests). These test are meant to be compiled on demand only, not during the standard building routine, for which a trick leveraging GNUmakefile-Makefile precedence with GNU make -was devised. +was devised (GNU make/gmake already required by configure script for +other reasons [some pattern-based matching not available with FreeBSD's +default "make", IIRC], so this introduces no new build dependency). The respective new tests are meant to simulate logging variants in two different library consumption models: @@ -56,7 +58,7 @@ Current state for this matrix, in which participants 1. - 3. map like: 3. ~ libX(Y) [a.k.a. interlib] and where "X(Y)" denotes "X linked with linker Y": X(a) .. ld.bfd < 2.29 - X(b) .. ld.bfd = 2.29 (and likely on), + X(b) .. ld.bfd = 2.29 (and only 2.29), goes like this: +=========+=========+=========+=========+=========+=========+=========+ @@ -68,6 +70,18 @@ goes like this: # x = b # BAD[*A] | BAD[*B] : BAD[*C] # BAD[*1] | BAD[*C] : BAD[*3] # +=========+=========+=========+=========+=========+=========+=========+ +whereas if we swap 2.29 for 2.29.1, i.e., X(b) .. ld.bfd = 2.29.1, we +can observe a somewhat simpler story (DEP ~ "depends"): + ++=========+=========+=========+=========+=========+=========+=========+ +#client(x)# libqb(a) usage # libqb(b) usage # +# vvv #---------+---------+---------+---------+---------+---------+ +# V # direct | libX(a) : libX(b) # direct | libX(a) : libX(b) # ++=========+=========+=========+=========+=========+=========+=========+ +# x = a # OK | OK : DEP[*J] # BAD[*1] | BAD[*1] : BAD[*L] # +# x = b # DEP[*I] | DEP[*I] : DEP[*K] # BAD[*1] | BAD[*1] : BAD[*L] # ++=========+=========+=========+=========+=========+=========+=========+ + [*1] client logging not working [*2] interlib logging not working [*3] both client and interlib logging not working @@ -81,15 +95,29 @@ goes like this: [*D] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side, which makes it boil down just to [*1] (hypothesis: mere internal self-reference to the section's boundary symbols makes them - overcome some kind of garbage collection at the linkage stage, - so they are exposed even they wouldn't be otherwise as demonstrated - with the initial, plain case of [*3]) + overcome some kind of symbol garbage collection at the linkage + stage, so they are exposed even they wouldn't be otherwise as + demonstrated with the initial, plain case of [*3]) + +[*I] boils down to [*1], unless QB_LOG_INIT_DATA used on client side, + which makes it, likely through self-reference keepalive (see + below) work OK +[*J] boils down to [*2], unless QB_LOG_INIT_DATA used on interlib side, + which makes it, likely through self-reference keepalive (see + below) work OK +[*K] boils down to [*3], unless QB_LOG_INIT_DATA used on both client + and interlib side, which makes it, likely through self-reference + keepalive (see below) work OK (it's expected that this a mere + composite of situations [*I] and [*J] with consequences as stated) +[*L] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side + (sufficient?), which makes it, likely through self-reference + keepalive (see below) boil down just to [*1] Note: as observed with [*D] case (libqb linked with ld.bfd < 2.29 whereas interlib and its client linked with ld.bfd = 2.29), the exact availability of a working logging doesn't depend solely on the linkers in question, but generally (further investigation out of scope) the -conclusion is that when 2.29+ ld.bfd is involved somewhere in the chain +conclusion is that when 2.29 ld.bfd is involved somewhere in the chain of logging-related discrete compilation units, also (self-)referencing of the section's boundary denoting symbols is a deciding factor whether particular logging source will be honored. This may be a result of @@ -114,10 +142,10 @@ Signed-off-by: Jan Pokorný tests/functional/log_interlib_client.c | 64 ++++++ tests/functional/log_interlib_client.err | 4 + tests/functional/log_internal/Makefile.am | 23 +++ - tests/functional/log_test_client.sh | 22 +++ - tests/functional/log_test_interlib_client.sh | 22 +++ - tests/functional/log_test_mock.sh | 285 +++++++++++++++++++++++++++ - 18 files changed, 704 insertions(+), 2 deletions(-) + tests/functional/log_test_client.sh | 22 ++ + tests/functional/log_test_interlib_client.sh | 22 ++ + tests/functional/log_test_mock.sh | 289 +++++++++++++++++++++++++++ + 16 files changed, 706 insertions(+), 2 deletions(-) create mode 100644 tests/functional/GNUmakefile create mode 100644 tests/functional/Makefile.am create mode 100644 tests/functional/log.am @@ -133,7 +161,7 @@ Signed-off-by: Jan Pokorný create mode 100755 tests/functional/log_test_mock.sh diff --git a/configure.ac b/configure.ac -index 727b8f0..db7bc68 100644 +index 478194c..274b49c 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ AC_CONFIG_SRCDIR([lib/ringbuffer.c]) @@ -145,7 +173,7 @@ index 727b8f0..db7bc68 100644 dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from dnl normal compilation. When a failure occurs, it will then display the full dnl command line -@@ -715,6 +715,9 @@ AC_CONFIG_FILES([Makefile +@@ -717,6 +717,9 @@ AC_CONFIG_FILES([Makefile lib/libqb.pc tools/Makefile tests/Makefile @@ -155,7 +183,7 @@ index 727b8f0..db7bc68 100644 tests/test.conf examples/Makefile docs/Makefile -@@ -722,6 +725,8 @@ AC_CONFIG_FILES([Makefile +@@ -724,6 +727,8 @@ AC_CONFIG_FILES([Makefile docs/html.dox docs/man.dox]) @@ -672,10 +700,10 @@ index 0000000..59c5555 +diff -u ../log_interlib_client.err log_interlib_client.err.real diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh new file mode 100755 -index 0000000..fb2c02c +index 0000000..4489718 --- /dev/null +++ b/tests/functional/log_test_mock.sh -@@ -0,0 +1,285 @@ +@@ -0,0 +1,289 @@ +#!/bin/sh +# Copyright 2017 Red Hat, Inc. +# @@ -736,6 +764,7 @@ index 0000000..fb2c02c +mock_args="-r fedora-27-${arch}" +pkg_binutils_228=binutils-2.28-14.fc27 +pkg_binutils_229=binutils-2.29-6.fc27 ++#pkg_binutils_229=binutils-2.29.1-2.fc28 # alternatively test with 2.29.1 + +# +# prettified reporters @@ -875,7 +904,7 @@ index 0000000..fb2c02c + | sed -n '/\.tar/{s|\.tar\.[^.]*$||;p;q}')" + + _resultsdir="_results/$(date '+%y%m%d_%H%M%S')_${_libqb_descriptor}" -+ test -z "${_makevars}" || _resultsdir="${_resultsdir}_sc" ++ test -z "${_makevars}" || _resultsdir="${_resultsdir}_nsc" + mkdir -p "${_resultsdir}" + rm -f -- "${_resultsdir}/*" + @@ -895,16 +924,19 @@ index 0000000..fb2c02c + esac + + do_progress "installing ${_pkg_binutils_libqb} so as to build" \ -+ " libqb [${_outfile_qb}]" ++ "libqb [${_outfile_qb}]" + do_install "${_pkg_binutils_libqb}" + + do_progress "building ${_libqb_descriptor_path} with" \ -+ " ${_pkg_binutils_libqb} [${_outfile_qb}]" ++ "${_pkg_binutils_libqb} [${_outfile_qb}]" + do_buildsrpm "${_libqb_descriptor_path}" "${_dist}" + + do_progress "installing ${_libqb_descriptor}-based packages" \ -+ " built with ${_pkg_binutils_libqb} [${_outfile_qb}]" ++ "built with ${_pkg_binutils_libqb} [${_outfile_qb}]" + do_install "${_libqb_descriptor}" ++ # from now on, we can work fully offline, also to speed ++ # the whole thing up (and not to bother the mirrors) ++ mock_args="${mock_args} --offline" + + for _pkg_binutils_interlib in none "${pkg_binutils_228}" "${pkg_binutils_229}"; do + @@ -919,11 +951,11 @@ index 0000000..fb2c02c + none) ;; + *) + do_progress "installing ${_pkg_binutils_interlib}" \ -+ " so as to build interlib [${_outfile}]" ++ "so as to build interlib [${_outfile}]" + do_install "${_pkg_binutils_interlib}" + + do_progress "building interlib with ${_libqb_descriptor_archive}" \ -+ " + ${_pkg_binutils_interlib} [${_outfile}]" ++ "+ ${_pkg_binutils_interlib} [${_outfile}]" + do_compile_interlib "${_libqb_descriptor_archive}" "${_makevars}" + ;; + esac @@ -940,10 +972,10 @@ index 0000000..fb2c02c + esac + + do_progress "installing ${_pkg_binutils_client}" \ -+ " so as to build ${_client} [${_outfile_client}]" ++ "so as to build ${_client} [${_outfile_client}]" + do_install "${_pkg_binutils_client}" + do_progress "building ${_client} with ${_libqb_descriptor_archive}" \ -+ " + ${_pkg_binutils_client} [${_outfile_client}]" ++ "+ ${_pkg_binutils_client} [${_outfile_client}]" + do_compile_and_test_client "${_libqb_descriptor_archive}" \ + "${_client}" "${_resultsdir}" \ + "${_outfile_client}" "${_makevars}" diff --git a/04-Med-add-extra-run-time-client-libqb-checks-that-logg.patch b/04-Med-add-extra-run-time-client-libqb-checks-that-logg.patch new file mode 100644 index 0000000..e99306b --- /dev/null +++ b/04-Med-add-extra-run-time-client-libqb-checks-that-logg.patch @@ -0,0 +1,490 @@ +From 0c8500a0c15f54250ce93c724451c36cde8b4499 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= +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 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] #|:# +# x = b # BAD[*A] | BAD[*B] : BAD[*C] #|:# ++=========+=========+=========+=========+=========+=========+=========+ + +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] #|:# +# x = b #| DEP[*I] :#|:# ++=========+=========+=========+=========+=========+=========+=========+ + +[*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ý +--- + 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 /* possibly needed for QB_LOG_INIT_DATA */ ++#include + #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 ++# ++# 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 . ++ ++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 + diff --git a/04-Med-add-extra-run-time-client-side-sanity-check-that.patch b/04-Med-add-extra-run-time-client-side-sanity-check-that.patch deleted file mode 100644 index 98c0b02..0000000 --- a/04-Med-add-extra-run-time-client-side-sanity-check-that.patch +++ /dev/null @@ -1,257 +0,0 @@ -From b883cc548ff1d487af6cd5bee49c5b386f91df4d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= -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 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] #|:# -# x = b # BAD[*A] | BAD[*B] : BAD[*C] #|:# -+=========+=========+=========+=========+=========+=========+=========+ - -[*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ý ---- - 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 -+#include -+#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 - diff --git a/05-High-bare-fix-for-libqb-logging-not-working-with-ld..patch b/05-High-bare-fix-for-libqb-logging-not-working-with-ld..patch index 97bdccd..ebf4b87 100644 --- a/05-High-bare-fix-for-libqb-logging-not-working-with-ld..patch +++ b/05-High-bare-fix-for-libqb-logging-not-working-with-ld..patch @@ -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?= Date: Fri, 6 Oct 2017 17:17:26 +0200 Subject: [PATCH 5/6] High: bare fix for libqb logging not working with @@ -34,7 +34,10 @@ above. And then for 2.29.1 release of binutils once again, as someone actually noticed something went overboard with the 2.29 changes: -https://sourceware.org/bugzilla/show_bug.cgi?id=21964 +http://lists.gnu.org/archive/html/bug-binutils/2017-08/msg00195.html +(overview of the original bug discussion, rather than directly +https://sourceware.org/bugzilla/show_bug.cgi?id=21964, which is +a result of a conflct resolution when restoring bugzilla backup) https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=487b6440dad57440939fab7afdd84a218b612796 At least that change doesn't invalidate all the effort being put into @@ -87,7 +90,8 @@ So further extensions were devised to cover both consumption models: libqb_la_LIBADD, and with a little bit of further fiddling, it works as desired (note that double occurrence of "-Wl,foo.t" equivalent present at some stages of sorting this trick turned out to be, - surprisingly, counter-productive); + surprisingly, counter-productive, which should now demistify the + very existence of effectively empty qblog_script_noop.ld file); NOTE: some forms of libtool distribution (debian + derivatives ones in particular) undermine natural transitive dependency propagation @@ -99,12 +103,30 @@ So further extensions were devised to cover both consumption models: of consuming libqb outside of it's own playground is hardly the Right Thing) if portability is important, nonetheless! +On the address of linker script workaround, there are linkers out there +that do not support the trick, for instance: +- ld.gold from binutils (but it has hardly ever been working with + orphan sections, anyway: + https://sourceware.org/bugzilla/show_bug.cgi?id=22291) +- ancient versions of ld.bfd, e.g. 10+ years old one used as a native + system linker even in the most recent releases of FreeBSD, unless + GCC toolchain is used instead +If these are hit when (because) the compiler has already demonstrated it +supports section attribute, the build system configuration is forcibly +stopped, simply to stay conceptually compatible with the prior state in +which the affinity to leverage that feature hasn't been called off +under any circumstances. One is, however, able to achieve exactly +this behaviour with --enable-nosection-fallback switch, but if some +other participants in the logging, possibly linked with a more friendly +linker, do utilize this orphan section, logging may silently break +(another reason to require an explicit sign-off). + Last but not least, libqb itself needs to be linked with the mentioned -"-Wl,foo.t" equivalent for its own outgoing log messages to be honoured, -which is already achieved with the arrangement for b. above, and by -experiments, further redefinition of those boundary denoting symbols -as weak was necessary so as to make them truly global within libqb.so -proper (at least with binutils 2.29). +"-Wl,foo.t" equivalent for its own outgoing log messages to be honoured +under all circumstances, which is already achieved with the arrangement +for b. above, and by experiments, further redefinition of those boundary +denoting symbols as weak was necessary so as to make them truly global +within libqb.so proper (at least with binutils 2.29). * * * @@ -112,7 +134,7 @@ Finally, let's have a look how the already well-known test matrix overview changes as of this commit, but first as a recap, "X(Y)" denotes "X linked with linker Y": X(a) .. ld.bfd < 2.29 - X(b) .. ld.bfd = 2.29 (and likely on) + X(b) .. ld.bfd = 2.29 (+ 2.29.1 and hopefully on) and here you are (values in denote non-trivial change [not mere rewording] introduced as of this commit, in comparison to the @@ -174,35 +196,38 @@ References: Signed-off-by: Jan Pokorný --- - configure.ac | 90 +++++++++++++++++++++++++++++++++++++++++------- - lib/Makefile.am | 67 +++++++++++++++++++++++++++++++++++ - lib/log.c | 7 ++++ - lib/qblog_script.la.in | 15 ++++++++ - lib/qblog_script.ld.in | 17 +++++++++ - lib/qblog_script_noop.ld | 1 + - 7 files changed, 184 insertions(+), 13 deletions(-) + configure.ac | 146 +++++++++++++++++++++++++++++++++++++++++------ + lib/Makefile.am | 67 ++++++++++++++++++++++ + lib/libqb.pc.in | 6 ++ + lib/log.c | 7 +++ + lib/qblog_script.la.in | 15 +++++ + lib/qblog_script.ld.in | 25 ++++++++ + lib/qblog_script_noop.ld | 1 + + 7 files changed, 249 insertions(+), 18 deletions(-) create mode 100644 lib/qblog_script.la.in create mode 100644 lib/qblog_script.ld.in create mode 100644 lib/qblog_script_noop.ld diff --git a/configure.ac b/configure.ac -index 5601302..6eda2dd 100644 +index 5769e60..57875c8 100644 --- a/configure.ac +++ b/configure.ac -@@ -501,6 +501,12 @@ AC_ARG_ENABLE([debug], +@@ -501,6 +501,14 @@ AC_ARG_ENABLE([debug], AC_ARG_ENABLE([coverage], [AS_HELP_STRING([--enable-coverage],[coverage analysis of the codebase])]) +AC_ARG_ENABLE([interlib-deps], + [AS_HELP_STRING([--disable-interlib-deps], -+ [disable inter-library dependencies (might break builds)])], -+ [enable_interlib_deps="$enableval"], -+ [enable_interlib_deps="yes"]) ++ [disable inter-library dependencies (might break builds)])]) ++ ++AC_ARG_ENABLE([nosection-fallback], ++ [AS_HELP_STRING([--enable-nosection-fallback], ++ [allow (logging compat-breaking?) fallback when orphan section dead-ended])]) + AC_ARG_ENABLE([slow-tests], [AS_HELP_STRING([--enable-slow-tests],[build and run slow tests])]) -@@ -609,6 +615,19 @@ else +@@ -609,6 +617,19 @@ else COVERAGE_LDFLAGS="" fi @@ -212,17 +237,17 @@ index 5601302..6eda2dd 100644 +# override the libtool variable by force because the current +# arrangement relies on transitive dependency propagation +AC_MSG_NOTICE([Enabling inter-library dependencies: $enable_interlib_deps]) -+if test "${enable_interlib_deps}" == "yes"; then -+ link_all_deplibs=yes -+else ++if test "x${enable_interlib_deps}" = xno; then + link_all_deplibs=no ++else ++ link_all_deplibs=yes +fi + +# --- slow tests --- if test "x${enable_slow_tests}" = xyes ; then AC_DEFINE([HAVE_SLOW_TESTS], 1,[have slow tests]) AC_MSG_NOTICE([Enabling Slow tests]) -@@ -618,31 +637,74 @@ AC_SUBST(HAVE_SLOW_TESTS) +@@ -618,33 +639,120 @@ AC_SUBST(HAVE_SLOW_TESTS) # --- callsite sections --- if test "x${GCC}" = xyes; then @@ -237,18 +262,22 @@ index 5601302..6eda2dd 100644 [[#include - extern void * __start___verbose, * __stop___verbose;]], - [[static int my_var __attribute__((section("__verbose"))) = 5; -- assert(("non-empty data section", __start___verbose != __stop___verbose)); -- assert(("no data section value loss", my_var == 5)); -- ]]), +- assert("non-empty data section" +- && __start___verbose != __stop___verbose); +- assert("no data section value loss" +- && my_var == 5);]] +- ), - [gcc_has_attribute_section=yes], -+ extern int __start___verbose[], __stop___verbose[]; -+ int test(void) { -+ static int my_var __attribute__((section("__verbose"))) = 3; -+ assert(("L:non-empty data section", __start___verbose != __stop___verbose)); -+ assert(("L:no data section value loss", my_var == 3 /* for 2.29.1+ */)); -+ return *((int *) __start___verbose); -+ }]])], -+ [gcc_has_attribute_section=yes; cp "conftest${EXEEXT}" "lib_conftest.so"], ++ extern int __start___verbose[], __stop___verbose[]; ++ int test(void) { ++ static int my_var __attribute__((section("__verbose"))) = 3; ++ assert("L:non-empty data section" ++ && __start___verbose != __stop___verbose); ++ assert("L:no data section value loss" ++ && my_var == 3 /* for 2.29.1+ */); ++ return *((int *) __start___verbose); }]] ++ )], ++ [gcc_has_attribute_section=yes; cp "conftest${EXEEXT}" "conftest.so"], [gcc_has_attribute_section=no] ) + AX_RESTORE_FLAGS @@ -258,6 +287,10 @@ index 5601302..6eda2dd 100644 - AC_MSG_RESULT($gcc_has_attribute_section) - if test $gcc_has_attribute_section = yes; then +- AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1, +- [Enabling code using __attribute__((section))]) +- PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section" +- AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS]) + + # in the failing case (e.g. with ld from binutils 2.29), it's likely the + # following will fail readily in linkage (hidden symbol `__stop___verbose' @@ -271,33 +304,76 @@ index 5601302..6eda2dd 100644 + # but the workaround is still provably needed + if test "x${gcc_has_attribute_section}" = xyes; then + AC_MSG_CHECKING([whether linker emits global boundary symbols for orphan sections]) -+ LIBS="${LIBS} -L. -l_conftest -Wl,-rpath=$(pwd)" ++ LIBS="${LIBS} -L. -l:conftest.so -Wl,-rpath=$(pwd)" + AC_TRY_RUN( + AC_LANG_PROGRAM( + [[#include -+ extern int __start___verbose[], __stop___verbose[]; -+ int test(void);]], ++ extern int __start___verbose[], __stop___verbose[]; ++ int test(void);]], + [[static int my_var __attribute__((section("__verbose"))) = 5; -+ assert(("P:non-empty data section", __start___verbose != __stop___verbose)); -+ assert(("P:no data section value loss", my_var == test() /*5?*/)); -+ ]]), ++ assert("P:non-empty data section" ++ && __start___verbose != __stop___verbose); ++ assert("P:no data section value loss" ++ && my_var == test() /*5?*/);]] ++ ), + [gcc_has_attribute_section_visible=yes], + [gcc_has_attribute_section_visible=no] + ) + AX_RESTORE_FLAGS + AC_MSG_RESULT($gcc_has_attribute_section_visible) -+ rm -f "lib_conftest.so" ++ rm -f "conftest.so" + - AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1, - [Enabling code using __attribute__((section))]) -- PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section" - AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS]) -+ if test "x${gcc_has_attribute_section_visible}" = xyes; then -+ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section" -+ else -+ AC_DEFINE([QB_NEED_ATTRIBUTE_SECTION_WORKAROUND], 1, ++ if test "x${gcc_has_attribute_section_visible}" = xno; then ++ # check if the linker script based workaround is ++ # feasible at all, otherwise fallback to using no ++ # section attribute while making some noise about it ++ # as combining with-without accustomed logging ++ # participants is currently uncharted waters ++ AC_MSG_CHECKING([whether linker workaround for orphan sections usable]) ++ >conftest.ld cat <<-EOF ++ SECTIONS { ++ __verbose : { ++ __start___verbose = .; ++ *(__verbose); ++ __stop___verbose = .; ++ } ++ } ++ EOF ++ LDFLAGS="${LDFLAGS} -Wl,conftest.ld" ++ AC_LINK_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ extern int __start___verbose[], __stop___verbose[]; ++ int test(void);]], ++ [[static int my_var __attribute__((section("__verbose"))) = 5; ++ assert("P:non-empty data section" ++ && __start___verbose != __stop___verbose); ++ assert("P:no data section value loss" ++ && my_var == 5);]] ++ )], ++ [], ++ [gcc_has_attribute_section=no] ++ ) ++ AX_RESTORE_FLAGS ++ AC_MSG_RESULT([$gcc_has_attribute_section]) ++ rm -f "conftest.ld" ++ fi ++ ++ if test "x${gcc_has_attribute_section}" = xyes; then ++ AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1, + [Enabling code using __attribute__((section))]) -+ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section-workaround" ++ AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS]) ++ if test "x${gcc_has_attribute_section_visible}" = xyes; then ++ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section" ++ else ++ AC_DEFINE([QB_NEED_ATTRIBUTE_SECTION_WORKAROUND], 1, ++ [Enabling code using __attribute__((section))]) ++ PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section-workaround" ++ fi ++ elif test "x${enable_nosection_fallback}" = xyes; then ++ AC_MSG_NOTICE([Falling back to not using orphan section]) ++ else ++ AC_MSG_ERROR([Would use section attribute, cannot; see --enable-nosection-fallback]) + fi fi fi @@ -308,7 +384,7 @@ index 5601302..6eda2dd 100644 # --- ansi --- if test "x${enable_ansi}" = xyes && \ -@@ -724,9 +786,11 @@ AC_CONFIG_FILES([Makefile +@@ -726,9 +834,11 @@ AC_CONFIG_FILES([Makefile docs/Makefile docs/common.dox docs/html.dox @@ -323,7 +399,7 @@ index 5601302..6eda2dd 100644 AC_OUTPUT diff --git a/lib/Makefile.am b/lib/Makefile.am -index 0bebeb5..340cd85 100644 +index 0bebeb5..ff5b3b4 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -19,6 +19,7 @@ @@ -389,7 +465,7 @@ index 0bebeb5..340cd85 100644 +qblog_script.ld: %.ld: %.ld.in + $(AM_V_GEN)$(CPP) -xc -I$(top_srcdir)/include -D_GNU_SOURCE -C -P $< \ -+ | sed -n "/$$(sed -n '/^[^#]/{s/[*\/]/\\\0/g;p;q}' $<)/{:r;p;n;br}" \ ++ | sed -n "/$$(sed -n '/^[^#]/{s/[*\/]/\\&/g;p;q;}' $<)/,$$ p" \ + > $@ + +# find the libqb.so symlink's target, if so, try to find out, iteratively, @@ -417,8 +493,24 @@ index 0bebeb5..340cd85 100644 pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libqb.pc +diff --git a/lib/libqb.pc.in b/lib/libqb.pc.in +index 37d27b7..bdcd3c8 100644 +--- a/lib/libqb.pc.in ++++ b/lib/libqb.pc.in +@@ -8,5 +8,11 @@ Version: @PACKAGE_VERSION@ + Description: libqb + Requires: + Libs: -L${libdir} -lqb @client_dlopen_LIBS@ ++# NOTE: If -lqb not usable for linking (e.g. linker not compatible with ++# linker scripts ad-hoc modifying output sections), try recent ++# ld.bfd/binutils linker first when available, otherwise you can ++# try "-l:libqb.so." link switch (right available, ++# for example, directly within libqb.so plaintext) that bypasses ++# said linker script -- but beware, logging problems may ensue. + Libs.private: @LIBS@ + Cflags: -I${includedir} diff --git a/lib/log.c b/lib/log.c -index bfd218f..4ed432f 100644 +index f30b8d8..e4b77d5 100644 --- a/lib/log.c +++ b/lib/log.c @@ -40,6 +40,13 @@ @@ -458,10 +550,10 @@ index 0000000..f262df8 +inherited_linker_flags=-Wl,@abs_builddir@/qblog_script.ld diff --git a/lib/qblog_script.ld.in b/lib/qblog_script.ld.in new file mode 100644 -index 0000000..1f37976 +index 0000000..fed826b --- /dev/null +++ b/lib/qblog_script.ld.in -@@ -0,0 +1,17 @@ +@@ -0,0 +1,25 @@ +#include +/* GNU ld script + This atypical arrangement enforces global visibility of boundary symbols @@ -469,7 +561,15 @@ index 0000000..1f37976 + QB_ATTR_SECTION used for compile-time offloading of the logging call sites + tracking. While libqb relies on these being global, default linker from + binutils change the visibility as of version 2.29, making the logging -+ unusable without artificial stimulus: https://bugzilla.redhat.com/1477354 */ ++ unusable without artificial stimulus: https://bugzilla.redhat.com/1477354 ++ ++ NOTE: If -lqb not usable for linking (e.g. linker not compatible with ++ linker scripts ad-hoc modifying output sections), try recent ++ ld.bfd/binutils linker first when available, otherwise you can ++ try "-l:libqb.so." link switch (right available, ++ for example, directly within libqb.so plaintext) that bypasses ++ said linker script -- but beware, logging problems may ensue. ++ */ +SECTIONS { +#ifdef QB_HAVE_ATTRIBUTE_SECTION + QB_ATTR_SECTION : { diff --git a/06-Low-fix-internal-object-symbol-s-leak-expose-run-tim.patch b/06-Low-fix-internal-object-symbol-s-leak-expose-run-tim.patch index 501f7f6..5ecb09e 100644 --- a/06-Low-fix-internal-object-symbol-s-leak-expose-run-tim.patch +++ b/06-Low-fix-internal-object-symbol-s-leak-expose-run-tim.patch @@ -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?= Date: Fri, 6 Oct 2017 17:17:26 +0200 Subject: [PATCH 6/6] Low: fix internal object symbol's leak & expose run-time @@ -19,19 +19,24 @@ lower-casing applied on originally upper-cased macro identifiers. Better than to roll out a futile data object serving as an artificial anchor for the above purpose, and this was a while due, afterall. +In turn, also bump "current" and "age" of fields of the libtool's +"-version-info" versioning system. + Signed-off-by: Jan Pokorný --- include/qb/qbconfig.h.in | 5 ++++- - include/qb/qblog.h | 10 ++++++---- + include/qb/qblog.h | 8 +++++--- include/qb/qbutil.h | 11 +++++++++++ + lib/Makefile.am | 2 +- + lib/log.c | 10 ++++++---- lib/log_format.c | 2 +- lib/util.c | 7 +++++++ tests/functional/log_client.c | 4 ++++ tests/functional/log_client.err | 2 +- - 7 files changed, 34 insertions(+), 7 deletions(-) + 9 files changed, 40 insertions(+), 11 deletions(-) diff --git a/include/qb/qbconfig.h.in b/include/qb/qbconfig.h.in -index c1852e1..789fff3 100644 +index c1852e1..1b92794 100644 --- a/include/qb/qbconfig.h.in +++ b/include/qb/qbconfig.h.in @@ -30,7 +30,10 @@ @@ -40,28 +45,26 @@ index c1852e1..789fff3 100644 -/* versioning info: MAJOR, MINOR, MICRO, and REST components */ +/* versioning info: MAJOR, MINOR, MICRO, and REST components; -+ note that static compile-time info is not that useful as run-time -+ querying the lower-cased symbolic constants directly from libqb ++ note that static compile-time info is not that useful as consulting ++ the lower-cased counterparts directly from libqb in run-time + (see qbutil.h), but that was only introduced after v1.0.2 */ #undef QB_VER_MAJOR #undef QB_VER_MINOR #undef QB_VER_MICRO diff --git a/include/qb/qblog.h b/include/qb/qblog.h -index e49c86c..7ca236d 100644 +index 9474c16..56fdd6a 100644 --- a/include/qb/qblog.h +++ b/include/qb/qblog.h -@@ -279,10 +279,12 @@ extern struct qb_log_callsite QB_ATTR_SECTION_STOP[]; - #define QB_NONAPI_LOG_INIT_DATA_EXTRA_ +@@ -293,9 +293,11 @@ extern struct qb_log_callsite QB_ATTR_SECTION_STOP[]; #else - #define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \ -- /* libqb sanity (locating libqb by it's relatively unique \ + #define QB_NONAPI_LOG_INIT_DATA_EXTRA_ \ + /* libqb sanity (locating libqb by it's relatively unique \ - -- and currently only such per-linkage global one -- \ - non-functional symbol, due to possible confusion otherwise) */ \ - if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli) \ -+ /* libqb sanity (locating libqb by it's relatively unique \ -+ non-functional symbol (the two are mutually exclusive, the \ ++ non-functional symbols -- the two are mutually exclusive, the \ + ordinarily latter was introduced by accident, the former is \ -+ intentional), due to possible confusion otherwise) */ \ ++ intentional -- due to possible confusion otherwise) */ \ + if ((dladdr(dlsym(RTLD_DEFAULT, "qb_ver_str"), &work_dli) \ + || dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli)) \ && (work_handle = dlopen(work_dli.dli_fname, \ @@ -89,6 +92,40 @@ index bfce349..a03bdf8 100644 /* *INDENT-OFF* */ #ifdef __cplusplus } +diff --git a/lib/Makefile.am b/lib/Makefile.am +index ff5b3b4..a428975 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -30,7 +30,7 @@ AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include + + lib_LTLIBRARIES = libqb.la + +-libqb_la_LDFLAGS = -version-info 18:2:18 ++libqb_la_LDFLAGS = -version-info 19:0:19 + + source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c \ + array.c loop.c loop_poll.c loop_job.c \ +diff --git a/lib/log.c b/lib/log.c +index e4b77d5..df5ce5c 100644 +--- a/lib/log.c ++++ b/lib/log.c +@@ -892,10 +892,12 @@ qb_log_init(const char *name, int32_t facility, uint8_t priority) + #ifdef QB_HAVE_ATTRIBUTE_SECTION + /* sanity check that target chain supplied QB_ATTR_SECTION_ST{ART,OP} + symbols and hence the local references to them are not referencing +- the proper libqb's ones (locating libqb-self by it's relatively +- unique -- and currently only such per-linkage global one -- +- non-functional symbol, due to possible confusion otherwise) */ +- if (dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli) ++ the proper libqb's ones (locating libqb by it's relatively unique ++ non-functional symbols -- the two are mutually exclusive, the ++ ordinarily latter was introduced by accident, the former is ++ intentional -- due to possible confusion otherwise) */ ++ if ((dladdr(dlsym(RTLD_DEFAULT, "qb_ver_str"), &work_dli) ++ || dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli)) + && (work_handle = dlopen(work_dli.dli_fname, + RTLD_LOCAL|RTLD_LAZY)) != NULL) { + work_s1 = (struct qb_log_callsite *) diff --git a/lib/log_format.c b/lib/log_format.c index 712f447..e7e1f40 100644 --- a/lib/log_format.c diff --git a/libqb.spec b/libqb.spec index ef8d76a..b41f8cf 100644 --- a/libqb.spec +++ b/libqb.spec @@ -2,7 +2,7 @@ Name: libqb Version: 1.0.2 -Release: 9%{?dist} +Release: 10%{?dist} Summary: An IPC library for high performance servers Group: System Environment/Libraries @@ -12,7 +12,7 @@ Source0: https://github.com/ClusterLabs/libqb/releases/download/v%{versio Patch0: 01-Med-qblog.h-better-explanation-behaviour-of-QB_LOG_I.patch Patch1: 02-build-configure-run-attribute-section-test-through-r.patch Patch2: 03-tests-new-sort-of-tests-dubbed-functional-cover-link.patch -Patch3: 04-Med-add-extra-run-time-client-side-sanity-check-that.patch +Patch3: 04-Med-add-extra-run-time-client-libqb-checks-that-logg.patch Patch4: 05-High-bare-fix-for-libqb-logging-not-working-with-ld..patch Patch5: 06-Low-fix-internal-object-symbol-s-leak-expose-run-tim.patch @@ -77,6 +77,9 @@ developing applications that use %{name}. %{_mandir}/man3/qb*3* %changelog +* Fri Oct 13 2017 Jan Pokorný - 1.0.2-10 +- Evolution of the previous (rhbz#1478089, rhbz#1487787) + * Mon Oct 09 2017 Jan Pokorný - 1.0.2-9 - Evolution of the previous (rhbz#1478089, rhbz#1487787)