From 1219a1fa255eb2bbaa01b1b763045742431a3203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Fri, 12 Jan 2018 14:36:38 +0100 Subject: [PATCH 1/9] tests: log_test_mock.sh: separate client-/interlib-side selfchecks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed to test more possible combinations, as apparently, failed assertion already on the client side will yield no visibility into how "interlib" would react, for instance. Signed-off-by: Jan Pokorný --- tests/functional/log_client.c | 13 ++++- tests/functional/log_interlib.c | 15 +++-- tests/functional/log_interlib_client.c | 2 +- tests/functional/log_test_mock.sh | 76 ++++++++++++++++++-------- 4 files changed, 74 insertions(+), 32 deletions(-) diff --git a/tests/functional/log_client.c b/tests/functional/log_client.c index d5d80890f..860127655 100644 --- a/tests/functional/log_client.c +++ b/tests/functional/log_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 Red Hat, Inc. + * Copyright 2018 Red Hat, Inc. * * All rights reserved. * @@ -27,6 +27,13 @@ QB_LOG_INIT_DATA(linker_contra_log); #endif +#ifndef NLOG +#define do_perror(msg) + qb_perror(LOG_ERR, msg) +#else + perror(msg) +#endif + static const char * my_tags_stringify(uint32_t tags) { @@ -76,14 +83,14 @@ main(int32_t argc, char *argv[]) blackbox file. */ tmpfile_fd = mkstemp(tmpfile_buf); if (tmpfile_fd == -1) { - qb_perror(LOG_ERR, "creating temporary file"); + do_perror("creating temporary file"); exit(EXIT_FAILURE); } unlink(tmpfile_buf); close(tmpfile_fd); #if 0 if (stat(tmpfile_buf, &tmpfile_stat) == -1) { - qb_perror(LOG_ERR, "stat'ing nonexistent temporary file"); + do_perror("stat'ing nonexistent temporary file"); exit(EXIT_FAILURE); } #endif diff --git a/tests/functional/log_interlib.c b/tests/functional/log_interlib.c index 228a339d8..257178f80 100644 --- a/tests/functional/log_interlib.c +++ b/tests/functional/log_interlib.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 Red Hat, Inc. + * Copyright 2018 Red Hat, Inc. * * All rights reserved. * @@ -23,10 +23,17 @@ #include "os_base.h" #include -#ifndef NSELFCHECK +#ifndef NLIBSELFCHECK QB_LOG_INIT_DATA(linker_contra_log_lib); #endif +#ifndef NLIBLOG +#define do_perror(msg) + qb_perror(LOG_ERR, msg) +#else + perror(msg) +#endif + void foo(void); void @@ -54,14 +61,14 @@ foo(void) blackbox file. */ tmpfile_fd = mkstemp(tmpfile_buf); if (tmpfile_fd == -1) { - qb_perror(LOG_ERR, "creating temporary file"); + do_perror("creating temporary file"); exit(EXIT_FAILURE); } unlink(tmpfile_buf); close(tmpfile_fd); #if 0 if (stat(tmpfile_buf, &tmpfile_stat) == -1) { - qb_perror(LOG_ERR, "stat'ing nonexistent temporary file"); + do_perror("stat'ing nonexistent temporary file"); exit(EXIT_FAILURE); } #endif diff --git a/tests/functional/log_interlib_client.c b/tests/functional/log_interlib_client.c index 820df67ce..f733958b9 100644 --- a/tests/functional/log_interlib_client.c +++ b/tests/functional/log_interlib_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 Red Hat, Inc. + * Copyright 2018 Red Hat, Inc. * * All rights reserved. * diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh index cdfce1fe2..b01071f88 100755 --- a/tests/functional/log_test_mock.sh +++ b/tests/functional/log_test_mock.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright 2017 Red Hat, Inc. +# Copyright 2018 Red Hat, Inc. # # Author: Jan Pokorny # @@ -195,24 +195,37 @@ do_proceed () { _makevars= _resultsdir_tag= - _selfcheck=1 + _clientselfcheck=1 + _interlibselfcheck=1 _clientlogging=1 _interliblogging=1 while :; do case "$1" in shell) shift; do_shell "$@"; return;; - -nsc) _resultsdir_tag="${_resultsdir_tag}$1"; shift; _selfcheck=0;; - -ncl) _resultsdir_tag="${_resultsdir_tag}$1"; shift; _clientlogging=0;; - -nil) _resultsdir_tag="${_resultsdir_tag}$1"; shift; _interliblogging=0;; - -*) do_die "Uknown option: $1";; - *) break;; + -nsc) case "${_resultsdir_tag}" in + *sc*) do_die "do not combine \"sc\" flags";; esac + _resultsdir_tag="${_resultsdir_tag}$1"; shift; + _clientselfcheck=0; _interlibselfcheck=0;; + -ncsc) case "${_resultsdir_tag}" in + *sc*) do_die "do not combine \"sc\" flags";; esac + _resultsdir_tag="${_resultsdir_tag}$1"; shift; _clientselfcheck=0;; + -nisc) case "${_resultsdir_tag}" in + *sc*) do_die "do not combine \"sc\" flags";; esac + _resultsdir_tag="${_resultsdir_tag}$1"; shift; _interlibselfcheck=0;; + -ncl) _resultsdir_tag="${_resultsdir_tag}$1"; shift; _clientlogging=0;; + -nil) _resultsdir_tag="${_resultsdir_tag}$1"; shift; _interliblogging=0;; + -*) do_die "Uknown option: $1";; + *) break;; esac done if test -n "${_resultsdir_tag}"; then - _makevars="CPPFLAGS=\"$(test "${_selfcheck}" -eq 1 || printf %s ' -DNSELFCHECK') \ + _makevars="CPPFLAGS=\" \ + $(test "${_clientselfcheck}" -eq 1 || printf %s ' -DNSELFCHECK') \ + $(test "${_interlibselfcheck}" -eq 1 || printf %s ' -DNLIBSELFCHECK') \ $(test "${_clientlogging}" -eq 1 || printf %s ' -DNLOG') \ - $(test "${_interliblogging}" -eq 1 || printf %s ' -DNLIBLOG')\"" + $(test "${_interliblogging}" -eq 1 || printf %s ' -DNLIBLOG') \ + \"" _makevars=$(echo ${_makevars}) fi @@ -243,6 +256,12 @@ do_proceed () { *) _outfile_qb="?";; esac + case "${_picktest}" in + ""|${_outfile_qb}*) ;; + *) do_progress "skipping '${_outfile_qb}' branch (no match with '${_picktest}')" + continue;; + esac + do_progress "installing ${_pkg_binutils_libqb} so as to build" \ "libqb [${_outfile_qb}]" do_install "${_pkg_binutils_libqb}" @@ -267,18 +286,22 @@ do_proceed () { *) _outfile="${_outfile_qb}_?";; esac - case "${_pkg_binutils_interlib}" in - none) ;; - *) - do_progress "installing ${_pkg_binutils_interlib}" \ - "so as to build interlib [${_outfile}]" - do_install "${_pkg_binutils_interlib}" - - do_progress "building interlib with ${_libqb_descriptor_archive}" \ - "+ ${_pkg_binutils_interlib} [${_outfile}]" \ - "{${_makevars}}" - do_compile_interlib "${_libqb_descriptor_archive}" "${_makevars}" - ;; + case "${_picktest}" in + ""|"${_outfile}*") + case "${_pkg_binutils_interlib}" in + none) ;; + *) + do_progress "installing ${_pkg_binutils_interlib}" \ + "so as to build interlib [${_outfile}]" + do_install "${_pkg_binutils_interlib}" + + do_progress "building interlib with ${_libqb_descriptor_archive}" \ + "+ ${_pkg_binutils_interlib} [${_outfile}]" \ + "{${_makevars}}" + do_compile_interlib "${_libqb_descriptor_archive}" "${_makevars}" + ;; + esac;; + *) do_progress "skipping dealing with interlib (no match with '${_picktest}')";; esac for _pkg_binutils_client in "${pkg_binutils_228}" "${pkg_binutils_229}"; do @@ -292,6 +315,9 @@ do_proceed () { *) _outfile_client="${_outfile}_?";; esac + test -n "${_picktest}" && test "${_picktest}" != "${_outfile_client}" \ + && continue + do_progress "installing ${_pkg_binutils_client}" \ "so as to build ${_client} [${_outfile_client}]" do_install "${_pkg_binutils_client}" @@ -307,9 +333,11 @@ do_proceed () { } { test $# -eq 0 || test "$1" = -h || test "$1" = --help; } \ - && printf '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ - "usage: $0 {[-n{sc,cl,il}]* | shell}" \ - "- use '-nsc' to suppress optional self-check (\"see whole story\")" \ + && printf '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ + "usage: $0 {[-n{{,c,i}sc,cl,il}]* | shell}" \ + "- use '-nsc' to suppress self-check (\"see whole story\") wholly" \ + "- use '-ncsc' to suppress self-check client-side only" \ + "- use '-nisc' to suppress self-check interlib-side only" \ "- use '-ncl' to suppress client-side logging" \ "- use '-nil' to suppress interlib-side logging" \ "- 'make -C ../.. srpm' (or so) can generate the requested input" \ From 5ee38db1d8dc71d72b1215c75e12bc86d5b47902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Thu, 11 Jan 2018 17:42:21 +0100 Subject: [PATCH 2/9] tests: log_test_mock.sh: allow for V=1 propagation to partial make's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- tests/functional/log_test_mock.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh index b01071f88..69cd57f22 100755 --- a/tests/functional/log_test_mock.sh +++ b/tests/functional/log_test_mock.sh @@ -202,6 +202,7 @@ do_proceed () { while :; do case "$1" in shell) shift; do_shell "$@"; return;; + -v) _makevars="${_makevars} V=1"; shift;; -nsc) case "${_resultsdir_tag}" in *sc*) do_die "do not combine \"sc\" flags";; esac _resultsdir_tag="${_resultsdir_tag}$1"; shift; @@ -220,7 +221,7 @@ do_proceed () { done if test -n "${_resultsdir_tag}"; then - _makevars="CPPFLAGS=\" \ + _makevars="${_makevars} CPPFLAGS=\" \ $(test "${_clientselfcheck}" -eq 1 || printf %s ' -DNSELFCHECK') \ $(test "${_interlibselfcheck}" -eq 1 || printf %s ' -DNLIBSELFCHECK') \ $(test "${_clientlogging}" -eq 1 || printf %s ' -DNLOG') \ @@ -333,8 +334,9 @@ do_proceed () { } { test $# -eq 0 || test "$1" = -h || test "$1" = --help; } \ - && printf '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ - "usage: $0 {[-n{{,c,i}sc,cl,il}]* | shell}" \ + && printf '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ + "usage: $0 {[-{v,n{{,c,i}sc,cl,il}}]* | shell}" \ + "- use '-v' to show the compilation steps verbosely" \ "- use '-nsc' to suppress self-check (\"see whole story\") wholly" \ "- use '-ncsc' to suppress self-check client-side only" \ "- use '-nisc' to suppress self-check interlib-side only" \ From 89d7ceee63fbbb674f9062ce03a280a20e09d279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Thu, 11 Jan 2018 19:21:19 +0100 Subject: [PATCH 3/9] tests: log_test_mock.sh: allow for selection of particular test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to cut down some time when only particular item of the test matrix is of interest, such as in ./log_test_mock.sh -v -ncl -ncsc -tqb+_il+_c+ command that can be used to highlight the issue with binutils 2.29+ compatibility fix making for a new issue when all of following are satisfied: - there are three link participants (reusing terminology establish in the patches constituting said fix) client program > intermediate library > libqb (client is not necessarily directly dependent on libqb) - client program is build-time linked using ld/binutils either < or >= 2.29 but with libqb 1.0.3 (containing the said fix, i.e., new linker script is in effect for building the client program) - client program does not use any logging at all - intermediate library triggers some checks when gets loaded, through usage of QB_LOG_INIT_DATA macro from qb/qblog.h, which are meant to check itself, but alas, the symbols to check on behalf of this library get run-time overridden with symbols of the client program, which only do exist because the libqb.so linker script (intended for other effect) made it happen despite the section is empty So far, log_test_mock.sh was only thoroughly run without any log-suppressing options (e.g. -ncl), which together with some extra linker/build flags (distro specific?) in case of compiling pacemaker (exercising the same scheme with some CLI utilities) masked this problem. [this all is still to be verified] This asks for a follow-up solution, and this commit is a good start as running whole matrix would keep increasing turnaround time needlessly (the new skipping harness is not ideal, but serves the purpose). Signed-off-by: Jan Pokorný --- tests/functional/log_test_mock.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh index 69cd57f22..e3dd59217 100755 --- a/tests/functional/log_test_mock.sh +++ b/tests/functional/log_test_mock.sh @@ -199,10 +199,16 @@ do_proceed () { _interlibselfcheck=1 _clientlogging=1 _interliblogging=1 + _picktest= while :; do case "$1" in shell) shift; do_shell "$@"; return;; -v) _makevars="${_makevars} V=1"; shift;; + -t=?*) _picktest=${1#-t=}; shift;; + -t=) do_die "missing -t option value";; + -t?*) _picktest=${1#-t}; shift;; + -t) test $# -gt 1 && { shift; _picktest=$1; } \ + || do_die "missing -t option value"; shift;; -nsc) case "${_resultsdir_tag}" in *sc*) do_die "do not combine \"sc\" flags";; esac _resultsdir_tag="${_resultsdir_tag}$1"; shift; @@ -334,9 +340,11 @@ do_proceed () { } { test $# -eq 0 || test "$1" = -h || test "$1" = --help; } \ - && printf '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ - "usage: $0 {[-{v,n{{,c,i}sc,cl,il}}]* | shell}" \ + && printf '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ + "usage: $0 {[-{v,t{, ,=},n{{,c,i}sc,cl,il}}]* | shell}" \ "- use '-v' to show the compilation steps verbosely" \ + "- use '-t[=]' to pick just one item of the test matrix" \ + " (pass the identifier matching the result file, e.g. qb+c-)" \ "- use '-nsc' to suppress self-check (\"see whole story\") wholly" \ "- use '-ncsc' to suppress self-check client-side only" \ "- use '-nisc' to suppress self-check interlib-side only" \ From 66371b2d363046720c9e351037a75d1678e61f0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Wed, 17 Jan 2018 16:27:11 +0100 Subject: [PATCH 4/9] tests: log_test_mock.sh: more output simplification + run optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also make the in-line progress show the actual output of the current test matrix item along with pre-existing syslog one for that very step. Signed-off-by: Jan Pokorný --- tests/functional/log_test_mock.sh | 38 +++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh index e3dd59217..df1e1568e 100755 --- a/tests/functional/log_test_mock.sh +++ b/tests/functional/log_test_mock.sh @@ -101,8 +101,8 @@ do_install () { # $1, ... $N: concrete packages to be installed do_install_inner () { - _remove_cmd="mock ${mock_args} -- shell \"rpm --nodeps --erase" - _install_cmd="mock ${mock_args}" + _remove_cmd="mock ${mock_args} -q -- shell \"rpm --nodeps --erase" + _install_cmd="mock ${mock_args} -q" while test $# -gt 0; do case "$1" in *.src.rpm|*-debuginfo*|*-debugsource*) ;; @@ -123,7 +123,7 @@ do_buildsrpm () { _pkg_descriptor="$(basename "$1" | sed 's|\.src\.rpm$||')" # need to prune due to possible duplicates caused by differing %{dist} rm -f -- "_pkgs/${_pkg_descriptor}"/* - mock ${mock_args} -Nn --define "dist $2" --define '_without_check 1' \ + mock ${mock_args} -q -Nn --define "dist $2" --define '_without_check 1' \ --resultdir "_pkgs/${_pkg_descriptor}" --rebuild "$1" } @@ -135,7 +135,9 @@ do_compile_interlib () { \( -name log_internal -o -name '*.c' \) -prune \ -o -name '*liblog_inter*' \ -exec rm -- {} \;" - mock ${mock_args} --shell "( cd \"builddir/build/BUILD/$1\"; ./configure )" + mock ${mock_args} --shell "( cd \"builddir/build/BUILD/$1\"; rm -f .ok; { \ + ./configure && touch .ok; } | grep -F 'section'; \ + test -f .ok || { cat config.log; exit 1; } )" mock ${mock_args} --shell \ "make -C \"builddir/build/BUILD/$1/tests/functional/log_external\" \ liblog_inter.la $2" @@ -167,7 +169,9 @@ do_compile_and_test_client () { ;; esac mock ${mock_args} --copyin "syslog-stdout.py" "builddir" - mock ${mock_args} --shell "( cd \"builddir/build/BUILD/$1\"; ./configure )" + mock ${mock_args} --shell "( cd \"builddir/build/BUILD/$1\"; rm -f .ok; { \ + ./configure && touch .ok; } | grep -F 'section'; \ + test -f .ok || { cat config.log; exit 1; } )" mock ${mock_args} --shell \ "python3 builddir/syslog-stdout.py \ >\"builddir/build/BUILD/$1/tests/functional/log_external/.syslog\" & \ @@ -176,8 +180,10 @@ do_compile_and_test_client () { && ! 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 ); \ + echo TESTLOG-begin; sed -n '/^\.\.\ /{:j;n;p;bj}' test-suite.log; \ + echo TESTLOG-end; \ + echo SYSLOG-begin; cat .syslog; echo SYSLOG-end; \ + cat .syslog >> test-suite.log ); \ ret () { return \$1; }; ret \${ret_ec}" \ && _result="${_result}_good" \ || _result="${_result}_bad" @@ -252,6 +258,7 @@ do_proceed () { _outfile= _outfile_client= _outfile_qb= + _last_binutils= do_download "${pkg_binutils_228}" "${pkg_binutils_229}" @@ -272,6 +279,7 @@ do_proceed () { do_progress "installing ${_pkg_binutils_libqb} so as to build" \ "libqb [${_outfile_qb}]" do_install "${_pkg_binutils_libqb}" + _last_binutils="${_pkg_binutils_libqb}" do_progress "building ${_libqb_descriptor_path} with" \ "${_pkg_binutils_libqb} [${_outfile_qb}]" @@ -297,10 +305,14 @@ do_proceed () { ""|"${_outfile}*") case "${_pkg_binutils_interlib}" in none) ;; + ${_last_binutils}) + do_progress "skipping redundant ${_pkg_binutils_interlib}" \ + "install so as to build interlib [${_outfile}]";; *) do_progress "installing ${_pkg_binutils_interlib}" \ "so as to build interlib [${_outfile}]" do_install "${_pkg_binutils_interlib}" + _last_binutils="${_pkg_binutils_interlib}" do_progress "building interlib with ${_libqb_descriptor_archive}" \ "+ ${_pkg_binutils_interlib} [${_outfile}]" \ @@ -325,9 +337,15 @@ do_proceed () { test -n "${_picktest}" && test "${_picktest}" != "${_outfile_client}" \ && continue - do_progress "installing ${_pkg_binutils_client}" \ - "so as to build ${_client} [${_outfile_client}]" - do_install "${_pkg_binutils_client}" + if test "${_pkg_binutils_client}" = "${_last_binutils}"; then + do_progress "skipping redundant ${_pkg_binutils_client}" \ + "install so as to build ${_client} [${_outfile_client}]" + else + do_progress "installing ${_pkg_binutils_client}" \ + "so as to build ${_client} [${_outfile_client}]" + do_install "${_pkg_binutils_client}" + _last_binutils="${_pkg_binutils_client}" + fi do_progress "building ${_client} with ${_libqb_descriptor_archive}" \ "+ ${_pkg_binutils_client} [${_outfile_client}]" \ "{${_makevars}}" From 92d693efdb3a51c62dc4716f6d3adb040f343fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Wed, 17 Jan 2018 20:31:24 +0100 Subject: [PATCH 5/9] tests: log_test_mock.sh: remember some inputs for the run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mainly to avoid duplicate runs because of those details getting lost as used to happen. Signed-off-by: Jan Pokorný --- tests/functional/log_test_mock.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh index df1e1568e..fabc02e54 100755 --- a/tests/functional/log_test_mock.sh +++ b/tests/functional/log_test_mock.sh @@ -206,6 +206,7 @@ do_proceed () { _clientlogging=1 _interliblogging=1 _picktest= + _args=$* while :; do case "$1" in shell) shift; do_shell "$@"; return;; @@ -253,6 +254,8 @@ do_proceed () { _resultsdir="_results/$(date '+%y%m%d_%H%M%S')_${_libqb_descriptor}${_resultsdir_tag}" mkdir -p "${_resultsdir}" rm -f -- "${_resultsdir}/*" + printf "args: %s\nbinutils [+]: %s\nbinutils [-]: %s\n" \ + "${_args}" "${pkg_binutils_228}" "${pkg_binutils_229}" > "${_resultsdir}/_env" _dist= _outfile= From 897c75449c568612fab9974e3381a3988bb3f533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Wed, 17 Jan 2018 15:16:33 +0100 Subject: [PATCH 6/9] tests: log_test_mock.sh: stop caring about line numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... as they can be neglected without any loss of check preciseness, and ignoring them makes for easier (isomorphic) changes in the future. Signed-off-by: Jan Pokorný --- tests/functional/log_client.c | 2 +- tests/functional/log_interlib_client.c | 2 +- tests/functional/log_test_client.err | 4 ++-- tests/functional/log_test_interlib_client.err | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/functional/log_client.c b/tests/functional/log_client.c index 860127655..e07836caf 100644 --- a/tests/functional/log_client.c +++ b/tests/functional/log_client.c @@ -58,7 +58,7 @@ main(int32_t argc, char *argv[]) qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); qb_log_tags_stringify_fn_set(my_tags_stringify); - qb_log_format_set(QB_LOG_STDERR, "[%5g|%p] %f:%l:%b"); + qb_log_format_set(QB_LOG_STDERR, "[%5g|%p] %f:%b"); #if 0 printf("\n==%s consists of: %d, %d, %d, %s==\n\n", qb_ver_str, diff --git a/tests/functional/log_interlib_client.c b/tests/functional/log_interlib_client.c index f733958b9..58d7f9eff 100644 --- a/tests/functional/log_interlib_client.c +++ b/tests/functional/log_interlib_client.c @@ -49,7 +49,7 @@ main(int argc, char *argv[]) qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); qb_log_tags_stringify_fn_set(my_tags_stringify); - qb_log_format_set(QB_LOG_STDERR, "[%5g|%p] %f:%l:%b"); + qb_log_format_set(QB_LOG_STDERR, "[%5g|%p] %f:%b"); #if 0 printf("--\n"); diff --git a/tests/functional/log_test_client.err b/tests/functional/log_test_client.err index 98df44ca7..52e4b2cb4 100644 --- a/tests/functional/log_test_client.err +++ b/tests/functional/log_test_client.err @@ -1,2 +1,2 @@ -[MAIN |debug] ../log_client.c:69:hello -[libqb|error] log_blackbox.c:196:qb_log_blackbox_print_from_file: +[MAIN |debug] ../log_client.c:hello +[libqb|error] log_blackbox.c:qb_log_blackbox_print_from_file: diff --git a/tests/functional/log_test_interlib_client.err b/tests/functional/log_test_interlib_client.err index 5b42b29e3..c83d9575a 100644 --- a/tests/functional/log_test_interlib_client.err +++ b/tests/functional/log_test_interlib_client.err @@ -1,4 +1,4 @@ -[MAIN |info] ../log_interlib_client.c:61:BEFORE -[MAIN |info] ../log_interlib.c:47:aloha -[libqb|error] log_blackbox.c:196:qb_log_blackbox_print_from_file: -[MAIN |info] ../log_interlib_client.c:65:AFTER +[MAIN |info] ../log_interlib_client.c:BEFORE +[MAIN |info] ../log_interlib.c:aloha +[libqb|error] log_blackbox.c:qb_log_blackbox_print_from_file: +[MAIN |info] ../log_interlib_client.c:AFTER From 3400a03ffbe6c51b22a7a5ca42af89b407efcce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 16 Jan 2018 20:39:47 +0100 Subject: [PATCH 7/9] tests: log_test_mock.sh: allow for "POSIX only" opt-in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consequently, turn original catch-all reliance on standard headers through "os_base.h" facade include into regular demand-driven ones, as the former had a side-effect of spoiling the included system headers with _GNU_SOURCE macro (through internal "config.h" unless HAVE_CONFIG_H is defined), which hence could not be undone by the means of command-line requested clearance of such macro, colliding hence with the objective of this change. Note that mere undefining of HAVE_CONFIG_H alone would not work, as the selected standard headers have to be included the alternative way, i.e. directly, so the compatibility of log_test_mock.sh with now-outdated SRPM would not be preserved for "POSIX only" test run, anyway (and in turn, "-UHAVE_CONFIG_H" is omitted here), hence the test to prevent this confusion is also added. Signed-off-by: Jan Pokorný --- tests/functional/log.am | 4 ++-- tests/functional/log_client.c | 15 +++++++++++---- tests/functional/log_interlib.c | 15 +++++++++++---- tests/functional/log_interlib_client.c | 7 ++++++- tests/functional/log_test_mock.sh | 16 ++++++++++++++-- 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/tests/functional/log.am b/tests/functional/log.am index f2c6fbcc9..4a489fac9 100644 --- a/tests/functional/log.am +++ b/tests/functional/log.am @@ -1,4 +1,4 @@ -# Copyright 2017 Red Hat, Inc. +# Copyright 2018 Red Hat, Inc. # # Author: Jan Pokorny # @@ -21,7 +21,7 @@ MAINTAINERCLEANFILES = Makefile.in CLEANFILES = log_test_client.err.real log_test_interlib_client.err.real \ ../log_callsite_bench.c -AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_builddir)/include -I$(top_srcdir)/include +AM_CPPFLAGS = -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_client.c b/tests/functional/log_client.c index e07836caf..7d9a889a2 100644 --- a/tests/functional/log_client.c +++ b/tests/functional/log_client.c @@ -20,7 +20,15 @@ * You should have received a copy of the GNU Lesser General Public License * along with libqb. If not, see . */ -#include "os_base.h" +#ifndef POSIXONLY +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include + #include #ifndef NSELFCHECK @@ -28,10 +36,9 @@ QB_LOG_INIT_DATA(linker_contra_log); #endif #ifndef NLOG -#define do_perror(msg) - qb_perror(LOG_ERR, msg) +#define do_perror(msg) qb_perror(LOG_ERR, msg) #else - perror(msg) +#define do_perror(msg) perror(msg) #endif static const char * diff --git a/tests/functional/log_interlib.c b/tests/functional/log_interlib.c index 257178f80..b8d5153b9 100644 --- a/tests/functional/log_interlib.c +++ b/tests/functional/log_interlib.c @@ -20,7 +20,15 @@ * You should have received a copy of the GNU Lesser General Public License * along with libqb. If not, see . */ -#include "os_base.h" +#ifndef POSIXONLY +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include + #include #ifndef NLIBSELFCHECK @@ -28,10 +36,9 @@ QB_LOG_INIT_DATA(linker_contra_log_lib); #endif #ifndef NLIBLOG -#define do_perror(msg) - qb_perror(LOG_ERR, msg) +#define do_perror(msg) qb_perror(LOG_ERR, msg) #else - perror(msg) +#define do_perror(msg) perror(msg) #endif void foo(void); diff --git a/tests/functional/log_interlib_client.c b/tests/functional/log_interlib_client.c index 58d7f9eff..72de3c98f 100644 --- a/tests/functional/log_interlib_client.c +++ b/tests/functional/log_interlib_client.c @@ -20,7 +20,12 @@ * You should have received a copy of the GNU Lesser General Public License * along with libqb. If not, see . */ -#include "os_base.h" +#ifndef POSIXONLY +#define _GNU_SOURCE +#endif + +#include + #include #ifndef NSELFCHECK diff --git a/tests/functional/log_test_mock.sh b/tests/functional/log_test_mock.sh index fabc02e54..1976db50f 100755 --- a/tests/functional/log_test_mock.sh +++ b/tests/functional/log_test_mock.sh @@ -150,8 +150,10 @@ do_compile_interlib () { # $5: extra (presumably) variable assignments for the make goal invocation do_compile_and_test_client () { _result=$4 + _checkfile= case "$2" in interclient) + _checkfile=log_interlib_client _logfile=log_test_interlib_client mock ${mock_args} --shell \ "find \"builddir/build/BUILD/$1/tests/functional\" \ @@ -160,6 +162,7 @@ do_compile_and_test_client () { -exec rm -- {} \;" ;; client|*) + _checkfile=log_client _logfile=log_test_client mock ${mock_args} --shell \ "find \"builddir/build/BUILD/$1/tests/functional\" \ @@ -168,6 +171,11 @@ do_compile_and_test_client () { -exec rm -- {} \;" ;; esac + if echo "$5" | grep -Fq POSIXONLY; then + mock ${mock_args} --shell \ + "grep -Fq POSIXONLY builddir/build/BUILD/$1/tests/functional/${_checkfile}.c" \ + || { echo "SRPM not -po switch compatible"; exit 1; } + fi mock ${mock_args} --copyin "syslog-stdout.py" "builddir" mock ${mock_args} --shell "( cd \"builddir/build/BUILD/$1\"; rm -f .ok; { \ ./configure && touch .ok; } | grep -F 'section'; \ @@ -200,6 +208,7 @@ do_shell () { do_proceed () { _makevars= + _posixonly=0 _resultsdir_tag= _clientselfcheck=1 _interlibselfcheck=1 @@ -211,6 +220,7 @@ do_proceed () { case "$1" in shell) shift; do_shell "$@"; return;; -v) _makevars="${_makevars} V=1"; shift;; + -po) _resultsdir_tag="${_resultsdir_tag}$1"; shift; _posixonly=1;; -t=?*) _picktest=${1#-t=}; shift;; -t=) do_die "missing -t option value";; -t?*) _picktest=${1#-t}; shift;; @@ -235,6 +245,7 @@ do_proceed () { if test -n "${_resultsdir_tag}"; then _makevars="${_makevars} CPPFLAGS=\" \ + $(test "${_posixonly}" -eq 0 || printf %s ' -DPOSIXONLY') \ $(test "${_clientselfcheck}" -eq 1 || printf %s ' -DNSELFCHECK') \ $(test "${_interlibselfcheck}" -eq 1 || printf %s ' -DNLIBSELFCHECK') \ $(test "${_clientlogging}" -eq 1 || printf %s ' -DNLOG') \ @@ -361,9 +372,10 @@ do_proceed () { } { test $# -eq 0 || test "$1" = -h || test "$1" = --help; } \ - && printf '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ - "usage: $0 {[-{v,t{, ,=},n{{,c,i}sc,cl,il}}]* | shell}" \ + && printf '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ + "usage: $0 {[-{v,po,t{, ,=},n{{,c,i}sc,cl,il}}]* | shell}" \ "- use '-v' to show the compilation steps verbosely" \ + "- use '-po' limit some self-checks to POSIX-only simplification" \ "- use '-t[=]' to pick just one item of the test matrix" \ " (pass the identifier matching the result file, e.g. qb+c-)" \ "- use '-nsc' to suppress self-check (\"see whole story\") wholly" \ From f9f180cdbcb189b6590e541502b1de658c81005e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Mon, 15 Jan 2018 00:02:36 +0100 Subject: [PATCH 8/9] High: qblog.h: fix overaggressive "callsite section populated" check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turned out that while log_test_mock.sh already provided ways for extra variations in the composite body of the program to inspect for a working logging, "omit logging at the target client side completely, leave it along with the respective self-check just at the intermediate library this program uses" one hadn't apparently been exercised with binutils < 2.29.1 (which is the only one OK from the get-go since it arranges boundary denoting symbols for orphan sections as protected). This made the pacemaker building fail half the way with libqb 1.0.3 and binutils < 2.29.1 because the built executables are instantly run as to extract their help screen[1], and they represent the said pain pattern: - program not using libqb log subsystem directly, but - linked to dynamic library that itself does + it also utilizes QB_LOG_INIT_DATA macro, which - upon loading the executable and the the linked dependencies prior to proper run invokes the checks, where - one in particular tries to assess whether the direct-access boundary symbols are not aliasing (equal), but - because with standard visibility, symbols from the program take a precedence, actually its symbols are prioritized (instead of the ones pertaining to the library layer as expected, remember that that check was intended as self-contained, targeting just it's own participating part in the link scheme), and - since previous fix to accommodate binutils 2.29+ fancy/new handling of the boundary symbols they are not subject to any sort of garbage collection (no symbols were emitted for a section that was not known because there were no instruction it should contain anything, until we stuck those symbols in place by force by the means of linker script to that effect), these boundary symbols indeed occur in this end program having no callsite data (see first point), meaning that start and stop address indications for the section equals, hence - the said assertion triggers (despite it should not = false positive), implying breach of self-containment of the check (which naturally cannot be responsible for any other linked part) This clearly means that "QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP" cannot be used unconditionally. However, it would left the software using logging along with QB_LOG_INIT_DATA macro (which was already highlighted as its vital part in order to avoid silent logging malfunction) that doesn't utilize _GNU_SOURCE macro (unlocking some GNU extensions on top of basic POSIX interface) short of the main checks (because they are conditionalized for requiring said extensions), and libqb never required the client side to define that macro nor it dared to define it behind user's back as it can have unexpected consequences. Luckily, the first paragraph carries the key: protected symbols behave exactly as required here[2]: > Protected visibility is like default visibility except that it > indicates that references within the defining module bind to the > definition in that module. That is, the declared entity cannot be > overridden by another module. So we just move said comparison to "!defined(_GNU_SOURCE)" conditional branch within qblog.h, and to cater binutils prior to 2.29.1 (which has it like that by default as mentioned), we also mark the declarations of the boundary symbols, likewise conditionally, with protected visilibity (there appears to be no way for that in the linker script). But that would be too easy as once again, 2.29 linker begs to differ and these two "!defined(_GNU_SOURCE)" measures will actually do more harm than good when in the mix. Hence, new QB_LD_2_29 macro is proclaimed the kill-switch for that case, and the user becomes responsible to either define it when building with this 2.29 troublemaker (as a recap, 2.29.1 is fine from this perspective), or to start using _GNU_SOURCE. One more question mark remains, though: are not the QB_LOG_INIT_DATA's checks in _GNU_SOURCE case weaker now than used to be? The anwer is: no, as long as looking at the symbols through dlopen'd particular shared object will contain no overrides from either already loaded dependencies (if caching is so aggressive to detect it's already in loaded in caller's context) or from recursive load. Currently, it doesn't seem to be the case, but it may depend on the implementation of dynamic linking library or the toolchain. If this observation is proved to be wrong, the solution may be as simple as dropping !defined(_GNU_C) condition from the guard of making the boundary symbols with protected visibility -- it is not done now also with respect to non-gcc compilers which may not recognize that. Last but not least, dl* calls in the QB_LOG_INIT_DATA's checks are themselves subject to scrutiny now: should they fail unexpectedly, the run is terminated just as well. This led to discovery of the issue masked so far, boiling down to unability to dlopen executable (as opposed to shared object)[3]. It did not matter before, because of rather best-effort, optimistic approach (perform the final check only if precondition steps succeeded), but now, we have to add an extra stipulation that this case won't lead to premature termination -- it just happens to sometimes be the case, and there's not much we can do to detect run down on the level of the executable proactively, at least not based on the brief experiments. [1] https://github.com/ClusterLabs/libqb/pull/266#issuecomment-356855212 [2] https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-visibility-function-attribute [3] https://sourceware.org/bugzilla/show_bug.cgi?id=11754 Signed-off-by: Jan Pokorný --- include/qb/qblog.h | 110 ++++++++++++++++++++++++++++++--------------- lib/libqb.pc.in | 10 ++++- lib/log.c | 2 + 3 files changed, 85 insertions(+), 37 deletions(-) diff --git a/include/qb/qblog.h b/include/qb/qblog.h index 59d56041c..5dfc4c668 100644 --- a/include/qb/qblog.h +++ b/include/qb/qblog.h @@ -1,5 +1,5 @@ /* - * Copyright 2017 Red Hat, Inc. + * Copyright 2018 Red Hat, Inc. * * All rights reserved. * @@ -83,6 +83,8 @@ extern "C" { * discern misuse of @c QB_LOG_INIT_DATA() macro in no-logging context from * broken callsite section handling assumptions owing to overboard fancy * linker -- situation that the self-check aims to detect in the first place. + * See also @ref qb_log_init_data_note_linker + * "important note on consideration when combined with binutils 2.29 linker". * * @par Configuring log targets. * A log target can be syslog, stderr, the blackbox, stdout, or a text file. @@ -298,23 +300,70 @@ typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs); #define QB_ATTR_SECTION_START_STR QB_PP_STRINGIFY(QB_ATTR_SECTION_START) #define QB_ATTR_SECTION_STOP_STR QB_PP_STRINGIFY(QB_ATTR_SECTION_STOP) -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_START[] +#if !defined(QB_NOAPI_LOG_INT) && !defined(_GNU_SOURCE) && !defined(QB_LD_2_29) +__attribute__((visibility("protected"))) +#endif +; +extern struct qb_log_callsite QB_ATTR_SECTION_STOP[] +#if !defined(QB_NOAPI_LOG_INT) && !defined(_GNU_SOURCE) && !defined(QB_LD_2_29) +__attribute__((visibility("protected"))) +#endif +; /* Related to the next macro that is -- unlike this one -- a public API */ -#ifndef _GNU_SOURCE +#if !defined(_GNU_SOURCE) && !defined(QB_LD_2_29) +#define QB_NONAPI_LOG_INIT_DATA_EXTRA_(name) \ + { _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 \ + and only superficially of the target site originating \ + this check alone. \ + NOT COMPATIBLE WITH BINUTILS 2.29 (2.29.1 OK)))); \ + /* original, straightforward check */ \ + assert("target's own callsite section is populated, otherwise \ +target's build is at fault, preventing reliable logging" \ + && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP); } +#elif !defined(_GNU_SOURCE) #define QB_NONAPI_LOG_INIT_DATA_EXTRA_(name) \ - _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 \ - nor of the target site originating this check alone))) + _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 \ + nor of the target site originating this check alone))) #else #define QB_NONAPI_LOG_INIT_DATA_EXTRA_(name) \ - { Dl_info work_dli; \ + { Dl_info work_dli; dlerror(); \ + /* sanity of the target site originating this check alone */ \ + if (dladdr(&(name), &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("target's own callsite section is observable, otherwise \ +target's own linkage at fault and logging would not work reliably \ +(unless QB_LOG_INIT_DATA macro used unexpectedly in no-logging context)"\ + && work_s1 != NULL && work_s2 != NULL); \ + assert("target's own callsite section is populated, otherwise \ +target's own linkage at fault and logging would not work reliably \ +(unless QB_LOG_INIT_DATA macro used unexpectedly in no-logging context)"\ + && work_s1 != work_s2); \ + dlclose(work_handle); \ + } else if (work_s1 != QB_ATTR_SECTION_START \ + && work_s2 != QB_ATTR_SECTION_STOP) { \ + /* skip "cannot dynamically load executable" \ + https://sourceware.org/bugzilla/show_bug.cgi?id=11754 */ \ + assert((fprintf(stderr, "%s\n", dlerror()), \ + !"can detect/dlopen/dlsym target")); \ + } else { \ + assert("executable's own callsite section is populated, \ +otherwise target's build is at fault, preventing reliable logging" \ + && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP); } \ /* libqb sanity (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) */ \ + dlerror(); \ if ((dladdr(dlsym(RTLD_DEFAULT, "qb_ver_str"), &work_dli) \ || dladdr(dlsym(RTLD_DEFAULT, "facilitynames"), &work_dli)) \ && (work_handle = dlopen(work_dli.dli_fname, \ @@ -329,24 +378,9 @@ libqb's build is at fault, preventing reliable logging" \ assert("libqb's callsite section is populated, otherwise \ libqb's build is at fault, preventing reliable logging" \ && work_s1 != work_s2); \ - dlclose(work_handle); } \ - /* sanity of the target site originating this check alone */ \ - if (dladdr(dlsym(RTLD_DEFAULT, QB_PP_STRINGIFY(name)), &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("target's own callsite section observable, otherwise \ -target's own linkage at fault and logging would not work reliably \ -(unless QB_LOG_INIT_DATA macro used unexpectedly in no-logging context)"\ - && work_s1 != NULL && work_s2 != NULL); \ - assert("target's own callsite section non-empty, otherwise \ -target's own linkage at fault and logging would not work reliably \ -(unless QB_LOG_INIT_DATA macro used unexpectedly in no-logging context)"\ - && work_s1 != work_s2); \ - dlclose(work_handle); } } + dlclose(work_handle); \ + } else { assert((fprintf(stderr, "%s\n", dlerror()), \ + !"can detect/dlopen/dlsym libqb")); } } #endif /* _GNU_SOURCE */ /** @@ -373,6 +407,13 @@ target's own linkage at fault and logging would not work reliably \ * @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. + * + * @anchor qb_log_init_data_note_linker + * @note When this macro is leveraged in the end executable that is moreover + * linked with ld.bfd from binutils 2.29 (2.29.1 is not of concern, + * though), make sure the respective code is compiled with at least one + * of @c _GNU_SOURCE and @c QB_LD_2_29 macros defined so as to avoid + * run-time misbehaviour of the pertaining checks. */ #define QB_LOG_INIT_DATA(name) \ void name(void); \ @@ -381,21 +422,20 @@ target's own linkage at fault and logging would not work reliably \ /* our own (target's) sanity, or possibly that of higher priority \ symbol resolution site (unless target equals end executable) \ or even the lower one if no such predecessor defines these */ \ + dlerror(); \ 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("implicit callsite section is observable, otherwise \ -target's and/or libqb's build is at fault, preventing reliable logging" \ +target's and/or libqb's build is at fault, preventing reliable logging" \ && work_s1 != NULL && work_s2 != NULL); \ - dlclose(work_handle); /* perhaps overly eager thing to do */ } \ - QB_NONAPI_LOG_INIT_DATA_EXTRA_(name); \ - /* finally, original, straightforward check */ \ - assert("implicit callsite section is populated, otherwise \ -target's build is at fault, preventing reliable logging" \ - && QB_ATTR_SECTION_START != QB_ATTR_SECTION_STOP); } \ - void __attribute__ ((constructor)) name(void); + dlclose(work_handle); /* perhaps overly eager thing to do */ \ + } else { assert((fprintf(stderr, "%s\n", dlerror()), \ + !"can dlopen/dlsym main program")); } \ + QB_NONAPI_LOG_INIT_DATA_EXTRA_(name); } \ + void __attribute__((constructor)) name(void); #else #define QB_LOG_INIT_DATA(name) #endif /* QB_HAVE_ATTRIBUTE_SECTION */ diff --git a/lib/libqb.pc.in b/lib/libqb.pc.in index d9839bf41..5368604b3 100644 --- a/lib/libqb.pc.in +++ b/lib/libqb.pc.in @@ -16,8 +16,14 @@ Libs: -L${libdir} -lqb @client_dlopen_LIBS@ # possible future optimizations and extra features. Consequently, # logging issues (typically bound to QB_LOG_INIT_DATA macro) can be # mitigated with QB_KILL_ATTRIBUTE_SECTION macro defined for a build. -# NOTE: when concerned about a warning coming from the build process like +# NOTE: Conversely, when QB_LOG_INIT_DATA macro is leveraged in the end +# executable relying on this library that is moreover linked with +# ld.bfd from binutils 2.29 (2.29.1 is not of concern, though), make +# sure the respective code is compiled with at least one of _GNU_SOURCE +# and QB_LD_2_29 macros defined so as to avoid run-time misbehaviour +# of the pertaining checks. +# NOTE: When concerned about a warning coming from the build process like # warning: [...]libqb.so contains output sections; did you forget -T? -# and the build finishes OK, take it merely as a harmless side-effect +# and the build finishes OK, take it merely as a harmless side-effect. Libs.private: @LIBS@ Cflags: -I${includedir} diff --git a/lib/log.c b/lib/log.c index 1339f9185..cd1e5877b 100644 --- a/lib/log.c +++ b/lib/log.c @@ -18,6 +18,8 @@ * You should have received a copy of the GNU Lesser General Public License * along with libqb. If not, see . */ +#define QB_NOAPI_LOG_INT 1 /* preventing explicit protected visibility */ + #include "os_base.h" #include #ifdef HAVE_LINK_H From 310882c58e5dc3f85e66961385a1295e088357cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Sun, 21 Jan 2018 12:41:08 +0100 Subject: [PATCH 9/9] Low: qblog.h: make callsite section usage depend also on __GNUC__ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not expected that basic prerequisite for using callsite section, notably section attribute, would work without the basic "GNU toolchain" support declared during the build. Signed-off-by: Jan Pokorný --- include/qb/qblog.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/include/qb/qblog.h b/include/qb/qblog.h index 5dfc4c668..998ee55dd 100644 --- a/include/qb/qblog.h +++ b/include/qb/qblog.h @@ -43,6 +43,14 @@ extern "C" { #undef QB_HAVE_ATTRIBUTE_SECTION #endif /* defined(QB_KILL_ATTRIBUTE_SECTION) || defined(S_SPLINT_S) */ +#if defined(QB_HAVE_ATTRIBUTE_SECTION) && !defined(__GNUC__) +_Pragma(QB_PP_STRINGIFY(message (QB_PP_STRINGIFY( \ + without GNU-compatible compiler (defining "__GNUC__") callsite \ + section cannot be used despite being supported by the platform \ + and not disabled; also QB_LOG_INIT_DATA is no-op, therefore)))); +#undef QB_HAVE_ATTRIBUTE_SECTION +#endif + #ifdef QB_HAVE_ATTRIBUTE_SECTION #include /* possibly needed for QB_LOG_INIT_DATA */ #include /* dynamic linking: dlopen, dlsym, dladdr, ... */ @@ -288,11 +296,12 @@ struct qb_log_callsite { typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs); -/* will be assigned by linker magic (assuming linker supports that): - * https://sourceware.org/binutils/docs/ld/Orphan-Sections.html - */ #ifdef QB_HAVE_ATTRIBUTE_SECTION +/* with proper toolchain support, linker magic backs the invisible counterpart: + https://sourceware.org/binutils/docs/ld/Orphan-Sections.html + + see also qb_logt below */ + #define QB_ATTR_SECTION __verbose /* conforms to C ident. */ #define QB_ATTR_SECTION_STR QB_PP_STRINGIFY(QB_ATTR_SECTION) #define QB_ATTR_SECTION_START QB_PP_JOIN(__start_, QB_ATTR_SECTION)