libqb/lib
Jan Pokorný cdb026998f
Med: add extra run-time (client, libqb) checks that logging will work
Now that the previous commit provides a foundation for what exactly can
go wrong with ld.bfd = 2.29+ linker, let's start reconciling that with
 some reasonable assurance that logging is not silently severed, because
realizing the logs are missing is otherwise bound to happen when the
logs are suddently pretty crucial analytical resource :-)
We'll proceed in two steps as detailed.

* * *

As a first step, the table below concludes how the test matrix overview
introduced with a message for the preceding commit (also introducing
log_test_mock.sh runner which got reused here) looks as of this
refreshed sanity check, once QB_LOG_INIT_DATA macro at hand gets applied
(meaning "for non-libqb logging participants" so as not complicate the
matrix further).  That macro is nothing triggered directly, it will just
plant a constructor-like function (to be invoked automatically early in
the execution) that will run through the checks (one original and couple
of new ones as of this changeset).

Note that for libqb users, this implies a new link dependency on libdl,
because they may opt-in for refreshed QB_LOG_INIT_DATA sanity check that
calls out to dlopen/dlsym/dladdr directly in case of "attribute section"
being available for the particular platform, and hence immediately needs
those symbols resolved in link time.  Hence, add this conditional link
dependency to libqb.pc pkg-config file under Libs variable -- we
actually restore the occurrence of "-ldl" there as it used to be present
until commit 56754d0.  While doing so, also move immediate link
dependencies of libqb (if any, currently not but that may be
a regression arising from the cleanup related to the mentioned commit)
represented with the LIBS autoconf variable under Libs.private variable
in libqb.pc, where it belongs per pkg-config documentation.

The promised table follows, but first as a recap, "X(Y)" denotes
"X linked with linker Y":
  X(a) .. ld.bfd < 2.29
  X(b) .. ld.bfd = 2.29 (and only 2.29)

goes like this (values in <angle brackets> denote non-trivial change
[not mere rewording] introduced as of this commit, in comparison to
the table stated in the preceding commit):

+=========+=========+=========+=========+=========+=========+=========+
#client(x)#        libqb(a) usage       #        libqb(b) usage       #
#   vvv   #---------+---------+---------+---------+---------+---------+
#    V    #  direct | libX(a) : libX(b) #  direct | libX(a) : libX(b) #
+=========+=========+=========+=========+=========+=========+=========+
#  x = a  #   OK    |   OK    : BAD[*2] #<BAD[*E]>|<BAD[*F]>:<BAD[*G]>#
#  x = b  # BAD[*A] | BAD[*B] : BAD[*C] #<BAD[*E]>|<BAD[*F]>:<BAD[*G]>#
+=========+=========+=========+=========+=========+=========+=========+

Woefully, nothing changes if we swap binutils 2.29 for 2.29.1, i.e.,
X(b) .. ld.bfd = 2.29.1, compared to previous state, i.e., the second
table from the previous commit is still applicable for that situation.
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 (and once it)
voluntarily initiates qb_log_init (delivering abruption all of a sudden
at some unanticipated, as opposed to a well-timed like with
constructors, execution point, seems pretty bad idea + libqb as
a library is a mere helper, not an undertaker :) -- this check then
only announces, via syslog (the only pre-enabled logging target),
the target's logging may be severed.

* * *

Hence, as a promised second step, after incorporating the syslog
change (and extending log_test_mock.sh so as to capture syslog
stream within the container), not much changes with the table above,
i.e., X(b) .. ld.bfd = 2.29:
[*A] in addition, unless QB_LOG_INIT_DATA used on client side,
     syslog carries this notice:
  "(libqb) log module hasn't observed target chain supplied callsite
   section, target's and/or libqb's build is at fault, preventing
   reliable logging (unless qb_log_init invoked in no-custom-logging
   context unexpectedly, or target chain built purposefully without
   these sections)"
     logged by libqb proper
[*C] in addition, unless QB_LOG_INIT_DATA used on interlib side,
     syslog carries this notice:
  "(libqb) log module hasn't observed target chain supplied callsite
   section, target's and/or libqb's build is at fault, preventing
   reliable logging (unless qb_log_init invoked in no-custom-logging
   context unexpectedly, or target chain built purposefully without
   these sections)"
     logged by libqb proper
[*E] in addition, unless QB_LOG_INIT_DATA used on client side,
     syslog carries this warning:
  "(libqb) log module has observed target chain supplied section
   unpopulated, target's and/or libqb's build is at fault, preventing
   reliable logging (unless qb_log_init invoked in no-custom-logging
   context unexpectedly)"
     logged by libqb proper
[*F] in addition, unless QB_LOG_INIT_DATA used on interlib side,
     syslog carries this warning:
  "(libqb) log module has observed target chain supplied section
   unpopulated, target's and/or libqb's build is at fault, preventing
   reliable logging (unless qb_log_init invoked in no-custom-logging
   context unexpectedly)"
     logged by libqb proper
[*G] in addition, unless QB_LOG_INIT_DATA used on interlib side,
     syslog carries this warning:
  "(libqb) log module has observed target chain supplied section
   unpopulated, target's and/or libqb's build is at fault, preventing
   reliable logging (unless qb_log_init invoked in no-custom-logging
   context unexpectedly)"
     logged by libqb proper

but desirably changes with "X(b) .. ld.bfd = 2.29.1" one
(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[*M]>|<BAD[*M]>:<BAD[*L]>#
#  x = b  #<DEP[*N]>| DEP[*I] :<DEP[*O]>#<BAD[*M]>|<BAD[*M]>:<BAD[*L]>#
+=========+=========+=========+=========+=========+=========+=========+

* * *

[*1] client logging not working
[*2] interlib logging not working
[*3] both client and interlib logging not working

[*A] boils down to [*1], unless QB_LOG_INIT_DATA used on client side,
     which then fails on
  "implicit callsite section is populated, otherwise target's build
   is at fault, preventing reliable logging"
     assertion
[*B] boils down to [*1], unless QB_LOG_INIT_DATA used on interlib side,
     which then fails on
  "implicit callsite section is populated, otherwise target's build
   is at fault, preventing reliable logging"
     assertion
[*C] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
     which then fails on
  "implicit callsite section is populated, otherwise target's build
   is at fault, preventing reliable logging"
     assertion
[*E] boils down to [*1], unless QB_LOG_INIT_DATA used on client side,
     which then fails on
  "implicit callsite section is self-observable, otherwise target's
   and/or libqb's build is at fault, preventing reliable logging"
     assertion
[*F] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
     which then fails on
  "libqb's callsite section is populated, otherwise libqb's build is
   at fault, preventing reliable logging"
     assertion
[*G] boils down to [*3], unless QB_LOG_INIT_DATA used on interlib side,
     which then fails on
  "implicit callsite section is self-observable, otherwise target's
   and/or libqb's build is at fault, preventing reliable logging"
     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 notice:
  "(libqb) log module hasn't observed target chain supplied callsite
   section, target's and/or libqb's build is at fault, preventing
   reliable logging (unless qb_log_init invoked in no-custom-logging
   context unexpectedly, or target chain built purposefully without
   these sections)"
     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 notice:
  "(libqb) log module hasn't observed target chain supplied callsite
   section, target's and/or libqb's build is at fault, preventing
   reliable logging (unless qb_log_init invoked in no-custom-logging
   context unexpectedly, or target chain built purposefully without
   these sections)"
     logged by libqb proper
[*M] boils down to [*1];
     in addition, syslog carries this notice:
  "(libqb) log module hasn't observed target chain supplied callsite
   section, target's and/or libqb's build is at fault, preventing
   reliable logging (unless qb_log_init invoked in no-custom-logging
   context unexpectedly, or target chain built purposefully without
   these sections)"
     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,
otherwise there's an imminent danger of possibly even run-terminating
false positive in the self-check mechanism!),

  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 shake is all about.

Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
2017-12-12 23:23:03 +01:00
..
.gitignore Cleanup the .gitignore files 2012-05-09 21:43:58 +10:00
array.c LOG: set the return code when calloc fails 2012-11-23 10:24:56 +11:00
atomic_int.h Add internal support for the new __atomic gcc builtins 2013-05-13 10:15:55 +10:00
hashtable.c Add the processing which remove notifier at skiplist_destroy function 2013-01-15 01:57:29 +09:00
hdb.c Unify to QB_TRUE/QB_FALSE a boolean value 2013-01-11 02:01:06 +09:00
ipc_int.h Allow Linux to use filesystem sockets (#248) 2017-04-28 16:13:02 +01:00
ipc_setup.c Allow Linux to use filesystem sockets (#248) 2017-04-28 16:13:02 +01:00
ipc_shm.c Med: rb: make it more robust against trivial IPC API misuses 2016-11-04 19:02:32 +01:00
ipc_socket.c Fix spelling: optvat -> optval (#270) 2017-10-13 12:45:11 +01:00
ipcc.c Doc tweaking (#261) 2017-07-20 15:21:51 +01:00
ipcs.c Low: sanitize import of <poll.h> symbols 2016-10-17 17:39:09 +02:00
libqb.pc.in Med: add extra run-time (client, libqb) checks that logging will work 2017-12-12 23:23:03 +01:00
log_blackbox.c Med: rb: make it more robust against trivial IPC API misuses 2016-11-04 19:02:32 +01:00
log_dcs.c LOG: copy the function/filename for dynamic callsites 2013-03-20 17:10:35 +11:00
log_file.c log: use fdatasync instead of fsync where possible (#263) 2017-08-07 10:52:02 +01:00
log_format.c Merge pull request #217 from jnpkrn/log-serialize-check-char-properly 2016-06-20 08:52:53 +01:00
log_int.h Feature: Implement "extended" logging using a marker character 2015-04-30 12:14:53 -04:00
log_syslog.c Get coverity to ignore this warning. 2012-02-03 14:42:25 +11:00
log_thread.c Refactor: log_thread: fix and diminish inferior comments 2016-10-21 09:42:48 +02:00
log.c Med: add extra run-time (client, libqb) checks that logging will work 2017-12-12 23:23:03 +01:00
loop_int.h LOOP: make it possible to pass in NULL as the default loop instance 2012-02-10 14:47:49 +11:00
loop_job.c Unify the list processing with qb_list function 2013-01-09 02:04:20 +09:00
loop_poll_epoll.c epoll: don't miss poll events under high load 2014-06-05 15:25:26 +10:00
loop_poll_int.h POLL: seperate out the poll/epoll and add kqueue 2012-04-04 00:26:20 +10:00
loop_poll_kqueue.c The udata member of the kevent struct is a void * 2015-01-23 01:58:02 +01:00
loop_poll_poll.c POLL: seperate out the poll/epoll and add kqueue 2012-04-04 00:26:20 +10:00
loop_poll.c loop: Fix splint error 2017-03-06 14:31:57 +00:00
loop_timerlist.c TIMER: check for null timer handle 2012-03-09 12:17:03 +11:00
loop.c Low: loop: don't bring runtime down for a trivial API misuse 2017-06-06 14:04:46 +01:00
Makefile.am lib: update library version for upcoming 1.0.2 release 2017-05-19 14:59:20 +01:00
map_int.h PTRIE: refcount the notifier structs 2012-01-25 16:09:32 +11:00
map.c MAP: add a notifier purely to allow the user to free memory. 2011-12-14 00:26:01 +11:00
ringbuffer_helper.c Med: rb: use new qb_rb_close_helper able to resort to file truncating 2016-11-04 19:05:35 +01:00
ringbuffer_int.h Med: rb: use new qb_rb_close_helper able to resort to file truncating 2016-11-04 19:05:35 +01:00
ringbuffer.c [tests] Fix qb_rb_chunk_peek test so it's consistent with qb_rb_read 2017-01-31 10:41:29 +00:00
rpl_sem.c rpl_sem: make destroy more compliant 2013-02-19 12:40:06 +11:00
rpl_sem.h rpl_sem: make destroy more compliant 2013-02-19 12:40:06 +11:00
skiplist.c Add the processing which remove notifier at skiplist_destroy function 2013-01-15 01:57:29 +09:00
strchrnul.c Use safer versions of string functions (strcpy -> strlcpy) 2012-02-08 22:00:49 +11:00
strlcat.c Fix strlcpy and strlcat functions 2012-12-19 10:42:08 +11:00
strlcpy.c Fix strlcpy and strlcat functions 2012-12-19 10:42:08 +11:00
trie.c High: trie: allow modifying the trie map during the notify callback 2014-07-30 09:58:04 -05:00
unix.c Low: unix: new qb_sys_unlink_or_truncate{,_at} helpers 2016-11-04 19:02:50 +01:00
util_int.h Fix typos: in{ -> s}tance, d{e -> i}stinguished 2017-06-06 14:04:46 +01:00
util.c Add Hurd support 2016-03-17 13:47:16 +01:00