[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#984501: unblock: libqb/2.0.3-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package libqb

Dear Release Team,

Upstream made a new minor release of libqb yesterday.  Since a new
upload wouldn't migrate before the hard freeze with the current 10 day
delay, I'm asking for an unblock in advance.

2.0.3 contains a single new feature extending the API and ABI in a
backwards-compatible way with a message-id parameter, which isn't the
main reason for this request.

Included are two doxygen2man fixes, one of them already present in the
current 2.0.2-1 package as a Debian patch, and another fixing a groff
error in libqb's own manual pages.

The really interesting stuff is a memory safety fix in the internal
strlcpy() implementation and a more thorough cleanup procedure, which
avoids filling up /dev/shm with stale files in certain error and
recovery conditions.

Locking errors (insufficient locking) are also fixed in the timer code,
and the unit tests are extended appropriately.

The last fix corrects another unit test but entails no change in
behaviour.

It would be possible to cherry pick the fix commits into Debian patches
leaving out the final one adding the new API, but I'd prefer the
cleaner solution of uploading 2.0.3 at this stage.

debdiff against the package in testing:

diff -Nru libqb-2.0.2/ChangeLog libqb-2.0.3/ChangeLog
--- libqb-2.0.2/ChangeLog	2020-12-03 14:07:32.000000000 +0100
+++ libqb-2.0.3/ChangeLog	2021-03-03 09:34:26.000000000 +0100
@@ -1,3 +1,57 @@
+2021-03-03  Christine Caulfield  <ccaulfie@redhat.com>
+
+	release: bump library version for 2.0.3 release
+
+2021-03-01  Aleksei Burlakov  <alex_burlakov@gmx.de>
+	    root  <Aleksei Burlakov>
+
+	syslog: Add a message-id parameter for messages (#433)
+	The message-id parameter will enable systemd catalogs.
+	To enable message-id's the libqb should be configured with the
+	 --enable-systemd-journal option.
+
+2021-02-08  Chrissie Caulfield  <ccaulfie@redhat.com>
+
+	tests: Fix up resources.test (#435)
+	resources.test has not checked the right filenames for a while.
+	Fix this, and also make sure we don't count (but remove) the dlock
+	test files.
+
+	timers: Add some locking (#436)
+	Fix several locking issues reported by helgrind
+
+2021-01-25  Chrissie Caulfield  <ccaulfie@redhat.com>
+
+	ipcc: Have a few goes at tidying up after a dead server (#434)
+	This is an attempt to make sure that /dev/shm is cleaned up when a
+	server exits unexpectedly. Normally it's the server's responsibility
+	to tidy up sockets, but if it crashes or is killed with SIGKILL then
+	the client (us) makes a reasonable attempt to tidy up the server sockets
+	we have connected. The extra delay here just gives the server chance to
+	disappear fully. As a client we can get here pretty quickly but shutting
+	down a large server may take a little longer even when SIGKILLed.
+	The 1/100th of a second is an arbitrary delay (of course) but seems to
+	catch most servers in 2 tries or less.
+
+2021-01-13  Chrissie Caulfield  <ccaulfie@redhat.com>
+
+	strlcpy: Check for maxlen underflow (#432)
+	* strlcpy: Check for maxlen underflow
+	https://github.com/ClusterLabs/libqb/issues/429
+	* Always terminate the string if maxlen is > 0
+
+2021-01-07  Chrissie Caulfield  <ccaulfie@redhat.com>
+
+	doxygen2man: fix printing of lines starting with '.' (#431)
+	if a line starts with a '.' (eg the '...' in qbarray.h) then
+	nroff thinks it's looking for a macro called '..'.
+	The easiest solution is to add a dummy format at the start of the line
+	(just adding \ seems not to work).
+
+2021-01-04  wferi  <wferi@debian.org>
+
+	doxygen2man: ignore all-whitespace brief descriptions (#430)
+
 2020-12-03  Christine Caulfield  <ccaulfie@redhat.com>
 
 	lib: Update library version for 2.0.2 release
diff -Nru libqb-2.0.2/configure libqb-2.0.3/configure
--- libqb-2.0.2/configure	2020-12-03 14:07:14.000000000 +0100
+++ libqb-2.0.3/configure	2021-03-03 09:34:07.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libqb 2.0.2.
+# Generated by GNU Autoconf 2.69 for libqb 2.0.3.
 #
 # Report bugs to <developers@clusterlabs.org>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='libqb'
 PACKAGE_TARNAME='libqb'
-PACKAGE_VERSION='2.0.2'
-PACKAGE_STRING='libqb 2.0.2'
+PACKAGE_VERSION='2.0.3'
+PACKAGE_STRING='libqb 2.0.3'
 PACKAGE_BUGREPORT='developers@clusterlabs.org'
 PACKAGE_URL=''
 
@@ -1426,7 +1426,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libqb 2.0.2 to adapt to many kinds of systems.
+\`configure' configures libqb 2.0.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1496,7 +1496,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libqb 2.0.2:";;
+     short | recursive ) echo "Configuration of libqb 2.0.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1649,7 +1649,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libqb configure 2.0.2
+libqb configure 2.0.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2426,7 +2426,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libqb $as_me 2.0.2, which was
+It was created by libqb $as_me 2.0.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4666,7 +4666,7 @@
 
 # Define the identity of the package.
  PACKAGE='libqb'
- VERSION='2.0.2'
+ VERSION='2.0.3'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -23074,7 +23074,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libqb $as_me 2.0.2, which was
+This file was extended by libqb $as_me 2.0.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -23140,7 +23140,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-libqb config.status 2.0.2
+libqb config.status 2.0.3
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -Nru libqb-2.0.2/debian/changelog libqb-2.0.3/debian/changelog
--- libqb-2.0.2/debian/changelog	2020-12-26 16:07:32.000000000 +0100
+++ libqb-2.0.3/debian/changelog	2021-03-04 06:11:31.000000000 +0100
@@ -1,3 +1,11 @@
+libqb (2.0.3-1) unstable; urgency=medium
+
+  * [f0b428b] New upstream release (2.0.3)
+  * [ff0eed7] Delete upstream patch, refresh the rest
+  * [bee0959] Acknowledge new symbols
+
+ -- Ferenc Wágner <wferi@debian.org>  Thu, 04 Mar 2021 06:11:31 +0100
+
 libqb (2.0.2-1) unstable; urgency=medium
 
   * [afb0870] libqb-tools took over qb-blackbox from libqb-dev (<< 2)
diff -Nru libqb-2.0.2/debian/libqb100.symbols libqb-2.0.3/debian/libqb100.symbols
--- libqb-2.0.2/debian/libqb100.symbols	2020-12-25 16:19:24.000000000 +0100
+++ libqb-2.0.3/debian/libqb100.symbols	2021-03-04 06:10:02.000000000 +0100
@@ -91,6 +91,7 @@
  qb_log_blackbox_open@Base 2.0.1
  qb_log_blackbox_print_from_file@Base 2.0.1
  qb_log_blackbox_write_to_file@Base 2.0.1
+ qb_log_callsite_get2@Base 2.0.3
  qb_log_callsite_get@Base 2.0.1
  qb_log_callsites_dump@Base 2.0.1
  qb_log_callsites_register@Base 2.0.1
@@ -114,6 +115,7 @@
  qb_log_format_init@Base 2.0.1
  qb_log_format_set@Base 2.0.1
  qb_log_from_external_source@Base 2.0.1
+ qb_log_from_external_source_va2@Base 2.0.3
  qb_log_from_external_source_va@Base 2.0.1
  qb_log_init@Base 2.0.1
  qb_log_priority2str@Base 2.0.1
diff -Nru libqb-2.0.2/debian/patches/doxygen2man-ignore-all-whitespace-brief-description.patch libqb-2.0.3/debian/patches/doxygen2man-ignore-all-whitespace-brief-description.patch
--- libqb-2.0.2/debian/patches/doxygen2man-ignore-all-whitespace-brief-description.patch	2020-12-26 16:07:22.000000000 +0100
+++ libqb-2.0.3/debian/patches/doxygen2man-ignore-all-whitespace-brief-description.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,21 +0,0 @@
-From: =?utf-8?q?Ferenc_W=C3=A1gner?= <wferi@debian.org>
-Date: Sat, 26 Dec 2020 16:06:28 +0100
-Subject: doxygen2man: ignore all-whitespace brief description
-
----
- doxygen2man/doxygen2man.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/doxygen2man/doxygen2man.c b/doxygen2man/doxygen2man.c
-index f7973fd..c1cb438 100644
---- a/doxygen2man/doxygen2man.c
-+++ b/doxygen2man/doxygen2man.c
-@@ -756,7 +756,7 @@ static void print_manpage(char *name, char *def, char *brief, char *args, char *
- 	fprintf(manfile, ".TH %s %s %s \"%s\" \"%s\"\n", allcaps(name), man_section, dateptr, package_name, header);
- 
- 	fprintf(manfile, ".SH NAME\n");
--	if (brief) {
-+	if (brief && not_all_whitespace(brief)) {
- 		fprintf(manfile, "%s \\- %s\n", name, brief);
- 	} else {
- 		fprintf(manfile, "%s\n", name);
diff -Nru libqb-2.0.2/debian/patches/Fix-typos-and-inconsistencies-in-doxygen2man-help-text.patch libqb-2.0.3/debian/patches/Fix-typos-and-inconsistencies-in-doxygen2man-help-text.patch
--- libqb-2.0.2/debian/patches/Fix-typos-and-inconsistencies-in-doxygen2man-help-text.patch	2020-12-26 16:06:56.000000000 +0100
+++ libqb-2.0.3/debian/patches/Fix-typos-and-inconsistencies-in-doxygen2man-help-text.patch	2021-03-04 05:50:39.000000000 +0100
@@ -7,10 +7,10 @@
  1 file changed, 9 insertions(+), 9 deletions(-)
 
 diff --git a/doxygen2man/doxygen2man.c b/doxygen2man/doxygen2man.c
-index d794b78..f7973fd 100644
+index dc96deb..4af9d38 100644
 --- a/doxygen2man/doxygen2man.c
 +++ b/doxygen2man/doxygen2man.c
-@@ -1109,7 +1109,7 @@ static void usage(char *name)
+@@ -1116,7 +1116,7 @@ static void usage(char *name)
  	printf(" using the name of the generated .xml file. This file will usually be called\n");
  	printf(" something like <include-file>_8h.xml, eg qbipcs_8h.xml\n");
  	printf("\n");
@@ -19,7 +19,7 @@
  	printf(" would do with any other man page.\n");
  	printf("\n");
  	printf("       -a            Print ASCII dump of man pages to stdout\n");
-@@ -1117,18 +1117,18 @@ static void usage(char *name)
+@@ -1124,18 +1124,18 @@ static void usage(char *name)
  	printf("       -P            Print PARAMS section\n");
  	printf("       -g            Print general man page for the whole header file\n");
  	printf("       -c            Use the Copyright date from the header file (if one can be found)\n");
diff -Nru libqb-2.0.2/debian/patches/series libqb-2.0.3/debian/patches/series
--- libqb-2.0.2/debian/patches/series	2020-12-26 16:07:22.000000000 +0100
+++ libqb-2.0.3/debian/patches/series	2021-03-04 05:50:39.000000000 +0100
@@ -3,4 +3,3 @@
 tests-always-run-the-SHM-suite-just-expect-failures.patch
 hurd-the-socket-tests-are-expected-to-fail.patch
 Fix-typos-and-inconsistencies-in-doxygen2man-help-text.patch
-doxygen2man-ignore-all-whitespace-brief-description.patch
diff -Nru libqb-2.0.2/doxygen2man/doxygen2man.c libqb-2.0.3/doxygen2man/doxygen2man.c
--- libqb-2.0.2/doxygen2man/doxygen2man.c	2020-11-13 16:31:46.000000000 +0100
+++ libqb-2.0.3/doxygen2man/doxygen2man.c	2021-01-07 10:09:05.000000000 +0100
@@ -222,7 +222,14 @@
 			buffer = cstring_append_chars(buffer, " ");
 		}
 		if (strcmp((char*)sub_tag->name, "text") == 0) {
-			buffer = cstring_append_chars(buffer, (char*)sub_tag->content);
+			// If the line starts with a dot then escape the first one to
+			// stop nroff thinking it's a macro
+			char *tmp = (char*)sub_tag->content;
+			if (tmp[0] == '.') {
+				buffer = cstring_append_chars(buffer, (char*)"\\[char46]");
+				tmp += 1;
+			}
+			buffer = cstring_append_chars(buffer, tmp);
 		}
 		if (strcmp((char*)sub_tag->name, "ref") == 0) {
 			// Handled by the child recusion below
@@ -756,7 +763,7 @@
 	fprintf(manfile, ".TH %s %s %s \"%s\" \"%s\"\n", allcaps(name), man_section, dateptr, package_name, header);
 
 	fprintf(manfile, ".SH NAME\n");
-	if (brief) {
+	if (brief && not_all_whitespace(brief)) {
 		fprintf(manfile, "%s \\- %s\n", name, brief);
 	} else {
 		fprintf(manfile, "%s\n", name);
diff -Nru libqb-2.0.2/include/qb/qbconfig.h libqb-2.0.3/include/qb/qbconfig.h
--- libqb-2.0.2/include/qb/qbconfig.h	2020-12-03 14:07:31.000000000 +0100
+++ libqb-2.0.3/include/qb/qbconfig.h	2021-03-03 09:34:24.000000000 +0100
@@ -36,7 +36,7 @@
    but that was only introduced after v1.0.2 */
 #define QB_VER_MAJOR 2
 #define QB_VER_MINOR 0
-#define QB_VER_MICRO 2
+#define QB_VER_MICRO 3
 #define QB_VER_REST ""
 
 #define QB_VER_STR   \
diff -Nru libqb-2.0.2/include/qb/qblog.h libqb-2.0.3/include/qb/qblog.h
--- libqb-2.0.2/include/qb/qblog.h	2020-10-14 11:43:49.000000000 +0200
+++ libqb-2.0.3/include/qb/qblog.h	2021-03-01 16:59:42.000000000 +0100
@@ -249,6 +249,7 @@
 
 /**
  * An instance of this structure is created for each log message
+ * with the message-id
  */
 struct qb_log_callsite {
 	const char *function;
@@ -258,6 +259,7 @@
 	uint32_t lineno;
 	uint32_t targets;
 	uint32_t tags;
+	const char *message_id;
 } __attribute__((aligned(8)));
 
 typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs);
@@ -319,6 +321,39 @@
 					    uint32_t lineno,
 					    uint32_t tags);
 
+/**
+ * Get or create a callsite at the given position.
+ * The same that qb_log_callsite_get but with the
+ * message_id parameter.
+ *
+ * The result can then be passed into qb_log_real_()
+ *
+ * @param message_id in the systemd catalog or NULL
+ * @param function originating function name
+ * @param filename originating filename
+ * @param format format string
+ * @param priority this takes syslog priorities.
+ * @param lineno file line number
+ * @param tags the tag
+ */
+struct qb_log_callsite* qb_log_callsite_get2(const char *message_id,
+					    const char *function,
+					    const char *filename,
+					    const char *format,
+					    uint8_t priority,
+					    uint32_t lineno,
+					    uint32_t tags);
+
+void qb_log_from_external_source_va2(const char *message_id,
+				    const char *function,
+				    const char *filename,
+				    const char *format,
+				    uint8_t priority,
+				    uint32_t lineno,
+				    uint32_t tags,
+				    va_list ap)
+	__attribute__ ((format (printf, 4, 0)));
+
 void qb_log_from_external_source_va(const char *function,
 				    const char *filename,
 				    const char *format,
@@ -332,6 +367,7 @@
  * This is the function to generate a log message if you want to
  * manually add tags.
  *
+ * @param message_id in the systemd catalog or NULL
  * @param priority this takes syslog priorities.
  * @param tags this is a uint32_t that you can use with
  *             qb_log_tags_stringify_fn_set() to "tag" a log message
@@ -340,13 +376,37 @@
  * @param fmt usual printf style format specifiers
  * @param args usual printf style args
  */
-#define qb_logt(priority, tags, fmt, args...) do {	\
+#define qb_logt2(message_id, priority, tags, fmt, args...) do {	\
 	struct qb_log_callsite* descriptor_pt =		\
-	qb_log_callsite_get(__func__, __FILE__, fmt,	\
+	qb_log_callsite_get2(message_id, __func__, __FILE__, fmt,	\
 			    priority, __LINE__, tags);	\
 	qb_log_real_(descriptor_pt, ##args);		\
     } while(0)
 
+/**
+ * This is the function to generate a log message if you want to
+ * manually add tags.
+ *
+ * @param priority this takes syslog priorities.
+ * @param tags this is a uint32_t that you can use with
+ *             qb_log_tags_stringify_fn_set() to "tag" a log message
+ *             with a feature or sub-system then you can use "%g"
+ *             in the format specifer to print it out.
+ * @param fmt usual printf style format specifiers
+ * @param args usual printf style args
+ */
+#define qb_logt(priority, tags, fmt, args...) qb_logt2(NULL, priority, tags, fmt, ##args)
+
+
+/**
+ * This is the main function to generate a log message.
+ *
+ * @param message_id in the systemd catalog or NULL
+ * @param priority this takes syslog priorities.
+ * @param fmt usual printf style format specifiers
+ * @param args usual printf style args
+ */
+#define qb_log2(message_id, priority, fmt, args...) qb_logt2(message_id, priority, 0, fmt, ##args)
 
 /**
  * This is the main function to generate a log message.
diff -Nru libqb-2.0.2/include/tlist.h libqb-2.0.3/include/tlist.h
--- libqb-2.0.2/include/tlist.h	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/include/tlist.h	2021-02-08 12:01:42.000000000 +0100
@@ -36,6 +36,7 @@
 
 struct timerlist {
 	struct qb_list_head timer_head;
+	pthread_mutex_t list_mutex;
 };
 
 struct timerlist_timer {
@@ -50,16 +51,20 @@
 static inline void timerlist_init(struct timerlist *timerlist)
 {
 	qb_list_init(&timerlist->timer_head);
+	pthread_mutex_init(&timerlist->list_mutex, NULL);
 	timerlist_hertz = qb_util_nano_monotonic_hz();
 }
 
-static inline void timerlist_add(struct timerlist *timerlist,
+static inline int32_t timerlist_add(struct timerlist *timerlist,
 				 struct timerlist_timer *timer)
 {
 	struct qb_list_head *timer_list = 0;
 	struct timerlist_timer *timer_from_list;
 	int32_t found = QB_FALSE;
 
+	if (pthread_mutex_lock(&timerlist->list_mutex)) {
+		return -errno;
+	}
 	qb_list_for_each(timer_list, &timerlist->timer_head) {
 
 		timer_from_list = qb_list_entry(timer_list,
@@ -74,6 +79,8 @@
 	if (found == QB_FALSE) {
 		qb_list_add_tail(&timer->list, &timerlist->timer_head);
 	}
+	pthread_mutex_unlock(&timerlist->list_mutex);
+	return 0;
 }
 
 static inline int32_t timerlist_add_duration(struct timerlist *timerlist,
@@ -82,6 +89,7 @@
 					 uint64_t nano_duration,
 					 timer_handle * handle)
 {
+	int res;
 	struct timerlist_timer *timer;
 
 	timer =
@@ -95,7 +103,11 @@
 	timer->data = data;
 	timer->timer_fn = timer_fn;
 	timer->handle_addr = handle;
-	timerlist_add(timerlist, timer);
+	res = timerlist_add(timerlist, timer);
+	if (res) {
+		free(timer);
+		return res;
+	}
 
 	*handle = timer;
 	return (0);
diff -Nru libqb-2.0.2/lib/ipc_shm.c libqb-2.0.3/lib/ipc_shm.c
--- libqb-2.0.2/lib/ipc_shm.c	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/lib/ipc_shm.c	2021-01-25 13:19:22.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010-2021 Red Hat, Inc.
  *
  * Author: Angus Salkeld <asalkeld@redhat.com>
  *
@@ -39,12 +39,43 @@
 qb_ipcc_shm_disconnect(struct qb_ipcc_connection *c)
 {
 	void (*rb_destructor)(struct qb_ringbuffer_s *);
-
 	rb_destructor = qb_rb_close;
-	if (!c->is_connected && (!c->server_pid || (kill(c->server_pid, 0) == -1 && errno == ESRCH))) {
+
+	/* This is an attempt to make sure that /dev/shm is cleaned up when a
+	 * server exits unexpectedly. Normally it's the server's responsibility
+	 * to tidy up sockets, but if it crashes or is killed with SIGKILL then
+	 * the client (us) makes a reasonable attempt to tidy up the server sockets
+	 * we have connected. The extra delay here just gives the server chance to
+	 * disappear fully. As a client we can get here pretty quickly but shutting
+	 * down a large server may take a little longer even when SIGKILLed.
+	 * The 1/100th of a second is an arbitrary delay (of course) but seems to
+	 * catch most servers in 2 tries or less.
+	 */
+	if (!c->is_connected && c->server_pid) {
+		int attempt = 0;
+		while (attempt++ <= 3 && rb_destructor == qb_rb_close) {
+			if (kill(c->server_pid, 0) == -1 && errno == ESRCH) {
+				rb_destructor = qb_rb_force_close;
+			} else {
+				struct timespec ts = {0, 10*QB_TIME_NS_IN_MSEC};
+				struct timespec ts_left = {0, 0};
+				nanosleep(&ts, &ts_left);
+			}
+		}
+	}
+	/*
+	 * On FreeBSD we don't have a server PID so tidy up anyway. The
+	 * server traps SIGBUS when cleaning up so will cope fine.
+	 */
+	if (!c->is_connected && !c->server_pid) {
 		rb_destructor = qb_rb_force_close;
 	}
 
+	if (rb_destructor == qb_rb_force_close) {
+		qb_util_log(LOG_DEBUG,
+			    "FORCE closing server sockets\n");
+	}
+
 	qb_ipcc_us_sock_close(c->setup.u.us.sock);
 
 	rb_destructor(qb_rb_lastref_and_ret(&c->request.u.shm.rb));
diff -Nru libqb-2.0.2/lib/log.c libqb-2.0.3/lib/log.c
--- libqb-2.0.2/lib/log.c	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/lib/log.c	2021-03-01 16:59:42.000000000 +0100
@@ -317,7 +317,8 @@
 }
 
 struct qb_log_callsite*
-qb_log_callsite_get(const char *function,
+qb_log_callsite_get2(const char *message_id,
+		    const char *function,
 		    const char *filename,
 		    const char *format,
 		    uint8_t priority,
@@ -335,8 +336,9 @@
 		return NULL;
 	}
 
-	cs = qb_log_dcs_get(&new_dcs, function, filename,
-			    format, priority, lineno, tags);
+	cs = qb_log_dcs_get(&new_dcs, message_id, function, filename,
+ 			    format, priority, lineno, tags);
+
 	if (cs == NULL) {
 		return NULL;
 	}
@@ -380,8 +382,21 @@
 	return cs;
 }
 
+struct qb_log_callsite*
+qb_log_callsite_get(const char *function,
+		    const char *filename,
+		    const char *format,
+		    uint8_t priority,
+		    uint32_t lineno,
+		    uint32_t tags)
+{
+	return qb_log_callsite_get2(NULL, function, filename, format,
+				    priority, lineno, tags);
+}
+
 void
-qb_log_from_external_source_va(const char *function,
+qb_log_from_external_source_va2(const char *message_id,
+			       const char *function,
 			       const char *filename,
 			       const char *format,
 			       uint8_t priority,
@@ -393,12 +408,23 @@
 		return;
 	}
 
-	cs = qb_log_callsite_get(function, filename,
+	cs = qb_log_callsite_get2(message_id, function, filename,
 				 format, priority, lineno, tags);
 	qb_log_real_va_(cs, ap);
 }
 
 void
+qb_log_from_external_source_va(const char *function,
+			       const char *filename,
+			       const char *format,
+			       uint8_t priority,
+			       uint32_t lineno, uint32_t tags, va_list ap)
+{
+	qb_log_from_external_source_va2(NULL, function, filename,
+				   format, priority, lineno, tags, ap);
+}
+
+void
 qb_log_from_external_source(const char *function,
 			    const char *filename,
 			    const char *format,
diff -Nru libqb-2.0.2/lib/log_dcs.c libqb-2.0.3/lib/log_dcs.c
--- libqb-2.0.2/lib/log_dcs.c	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/lib/log_dcs.c	2021-03-01 16:59:42.000000000 +0100
@@ -58,7 +58,8 @@
 }
 
 static struct qb_log_callsite *
-_log_dcs_new_cs(const char *function,
+_log_dcs_new_cs(const char *message_id,
+		const char *function,
 		const char *filename,
 		const char *format,
 		uint8_t priority, uint32_t lineno, uint32_t tags)
@@ -70,6 +71,7 @@
 	assert(rc == 0);
 	assert(cs != NULL);
 
+	cs->message_id = message_id ? strdup(message_id) : NULL;
 	cs->function = strdup(function);
 	cs->filename = strdup(filename);
 	cs->format = strdup(format);
@@ -82,6 +84,7 @@
 
 struct qb_log_callsite *
 qb_log_dcs_get(int32_t * newly_created,
+	       const char *message_id,
 	       const char *function,
 	       const char *filename,
 	       const char *format,
@@ -120,6 +123,7 @@
 	(void)qb_thread_lock(arr_next_lock);
 	if (csl_head->cs &&
 		priority == csl_head->cs->priority &&
+		(message_id ? (strcmp(message_id, csl_head->cs->message_id) == 0) : 1) &&
 		strcmp(safe_filename, csl_head->cs->filename) == 0 &&
 		strcmp(safe_format, csl_head->cs->format) == 0) {
 		(void)qb_thread_unlock(arr_next_lock);
@@ -130,7 +134,8 @@
 	 * so we will either have to create it or go through a list
 	 */
 	if (csl_head->cs == NULL) {
-		csl_head->cs = _log_dcs_new_cs(safe_function, safe_filename, safe_format,
+		csl_head->cs = _log_dcs_new_cs(message_id, safe_function,
+					       safe_filename, safe_format,
 					       priority, lineno, tags);
 		cs = csl_head->cs;
 		csl_head->next = NULL;
@@ -152,7 +157,8 @@
 			if (csl == NULL) {
 				goto cleanup;
 			}
-			csl->cs = _log_dcs_new_cs(safe_function, safe_filename, safe_format,
+			csl->cs = _log_dcs_new_cs(message_id, safe_function,
+						  safe_filename, safe_format,
 						  priority, lineno, tags);
 			csl->next = NULL;
 			csl_last->next = csl;
diff -Nru libqb-2.0.2/lib/log_int.h libqb-2.0.3/lib/log_int.h
--- libqb-2.0.2/lib/log_int.h	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/lib/log_int.h	2021-03-01 16:59:42.000000000 +0100
@@ -125,6 +125,7 @@
 void qb_log_dcs_init(void);
 void qb_log_dcs_fini(void);
 struct qb_log_callsite *qb_log_dcs_get(int32_t *newly_created,
+				       const char *message_id,
 				       const char *function,
 				       const char *filename,
 				       const char *format,
diff -Nru libqb-2.0.2/lib/log_syslog.c libqb-2.0.3/lib/log_syslog.c
--- libqb-2.0.2/lib/log_syslog.c	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/lib/log_syslog.c	2021-03-01 16:59:42.000000000 +0100
@@ -64,13 +64,24 @@
 	}
 #ifdef USE_JOURNAL
 	if (t->use_journal) {
-		sd_journal_send("PRIORITY=%d", final_priority,
+		if (cs->message_id) {
+			sd_journal_send("MESSAGE_ID=%s", cs->message_id,
+				"PRIORITY=%d", final_priority,
 				"CODE_LINE=%d", cs->lineno,
 				"CODE_FILE=%s", cs->filename,
 				"CODE_FUNC=%s", cs->function,
 				"SYSLOG_IDENTIFIER=%s", t->name,
 				"MESSAGE=%s", output_buffer,
 				NULL);
+		} else {
+			sd_journal_send("PRIORITY=%d", final_priority,
+				"CODE_LINE=%d", cs->lineno,
+				"CODE_FILE=%s", cs->filename,
+				"CODE_FUNC=%s", cs->function,
+				"SYSLOG_IDENTIFIER=%s", t->name,
+				"MESSAGE=%s", output_buffer,
+				NULL);
+		}
 	} else {
 #endif
 		syslog(final_priority, "%s", output_buffer);
diff -Nru libqb-2.0.2/lib/loop_timerlist.c libqb-2.0.3/lib/loop_timerlist.c
--- libqb-2.0.2/lib/loop_timerlist.c	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/lib/loop_timerlist.c	2021-02-08 12:01:42.000000000 +0100
@@ -44,6 +44,7 @@
 	struct timerlist timerlist;
 	qb_array_t *timers;
 	size_t timer_entry_count;
+	pthread_mutex_t lock;
 };
 
 static void
@@ -104,6 +105,7 @@
 	timerlist_init(&my_src->timerlist);
 	my_src->timers = qb_array_create_2(16, sizeof(struct qb_loop_timer), 16);
 	my_src->timer_entry_count = 0;
+	pthread_mutex_init(&my_src->lock, NULL);
 
 	return (struct qb_loop_source *)my_src;
 }
@@ -192,6 +194,9 @@
 	}
 	my_src = (struct qb_timer_source *)l->timer_source;
 
+	if (pthread_mutex_lock(&my_src->lock)) {
+		return -errno;
+	}
 	i = _get_empty_array_position_(my_src);
 	assert(qb_array_index(my_src->timers, i, (void **)&t) >= 0);
 	t->state = QB_POLL_ENTRY_ACTIVE;
@@ -202,6 +207,9 @@
 	t->p = p;
 	qb_list_init(&t->item.list);
 
+	/* Unlock here to stop anyone else changing the state while we're initializing */
+	pthread_mutex_unlock(&my_src->lock);
+
 	/*
 	 * Make sure just positive integers are used for the integrity(?)
 	 * checks within 2^32 address space, if we miss 200 times in a row
diff -Nru libqb-2.0.2/lib/Makefile.am libqb-2.0.3/lib/Makefile.am
--- libqb-2.0.2/lib/Makefile.am	2020-12-03 14:04:26.000000000 +0100
+++ libqb-2.0.3/lib/Makefile.am	2021-03-03 09:26:31.000000000 +0100
@@ -30,7 +30,7 @@
 
 lib_LTLIBRARIES		= libqb.la
 
-libqb_la_LDFLAGS	= -version-info 101:0:1
+libqb_la_LDFLAGS	= -version-info 102:0:2
 
 source_to_lint		= util.c hdb.c ringbuffer.c ringbuffer_helper.c \
 			  array.c loop.c loop_poll.c loop_job.c \
diff -Nru libqb-2.0.2/lib/Makefile.in libqb-2.0.3/lib/Makefile.in
--- libqb-2.0.2/lib/Makefile.in	2020-12-03 14:07:18.000000000 +0100
+++ libqb-2.0.3/lib/Makefile.in	2021-03-03 09:34:10.000000000 +0100
@@ -465,7 +465,7 @@
 
 AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
 lib_LTLIBRARIES = libqb.la
-libqb_la_LDFLAGS = -version-info 101:0:1
+libqb_la_LDFLAGS = -version-info 102:0:2
 source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c \
 			  array.c loop.c loop_poll.c loop_job.c \
 			  loop_timerlist.c ipcc.c ipcs.c ipc_shm.c \
diff -Nru libqb-2.0.2/lib/strlcpy.c libqb-2.0.3/lib/strlcpy.c
--- libqb-2.0.2/lib/strlcpy.c	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/lib/strlcpy.c	2021-01-13 15:12:21.000000000 +0100
@@ -33,8 +33,12 @@
 	size_t	srclen = strlen(src);
 	size_t	len2cpy = QB_MIN(maxlen-1, srclen);
 
-	if (len2cpy > 0) {
-		strncpy(dest, src, len2cpy+1);
+	/* check maxlen separately as it could have underflowed from 0 above. */
+	if (maxlen) {
+		if (len2cpy > 0) {
+			strncpy(dest, src, len2cpy+1);
+		}
+		/* Always terminate, even if its empty */
 		dest[len2cpy] = '\0';
 	}
 	return srclen;
diff -Nru libqb-2.0.2/source_epoch libqb-2.0.3/source_epoch
--- libqb-2.0.2/source_epoch	2020-12-03 14:07:32.000000000 +0100
+++ libqb-2.0.3/source_epoch	2021-03-03 09:34:26.000000000 +0100
@@ -1 +1 @@
-1607000743
+1614760329
diff -Nru libqb-2.0.2/.tarball-version libqb-2.0.3/.tarball-version
--- libqb-2.0.2/.tarball-version	2020-12-03 14:07:32.000000000 +0100
+++ libqb-2.0.3/.tarball-version	2021-03-03 09:34:26.000000000 +0100
@@ -1 +1 @@
-2.0.2
+2.0.3
diff -Nru libqb-2.0.2/tests/check_log.c libqb-2.0.3/tests/check_log.c
--- libqb-2.0.2/tests/check_log.c	2020-11-18 13:45:20.000000000 +0100
+++ libqb-2.0.3/tests/check_log.c	2021-03-01 16:59:42.000000000 +0100
@@ -1021,12 +1021,13 @@
 	pid_t log_pid;
 	sd_journal *jnl;
 	int count = 0;
+	const char *msgid="f77379a8490b408bbe5f6940505a777b";
 
 	qb_log_init("check_log", LOG_USER, LOG_DEBUG);
 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
 	rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_USE_JOURNAL, 1);
 	ck_assert_int_eq(rc, 0);
-	qb_log(LOG_ERR, "Test message 1 from libqb");
+	qb_log2(msgid, LOG_ERR, "Test message 1 from libqb");
 
 	qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
 	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_USE_JOURNAL, 1);
@@ -1046,6 +1047,9 @@
 	    if (log_pid == getpid()) {
 	        rc = sd_journal_get_data(jnl, "MESSAGE", (const void **)&msg, &len);
 		ck_assert_int_eq(rc, 0);
+	        rc = sd_journal_get_data(jnl, "MESSAGE_ID", (const void **)&msg, &len);
+		ck_assert_int_eq(rc, 0);
+		ck_assert_str_eq(msg+11, msgid);
 		break;
 	    }
 	    if (++count > 20) {
diff -Nru libqb-2.0.2/tests/check_loop.c libqb-2.0.3/tests/check_loop.c
--- libqb-2.0.2/tests/check_loop.c	2020-12-03 11:49:29.000000000 +0100
+++ libqb-2.0.3/tests/check_loop.c	2021-02-08 12:01:42.000000000 +0100
@@ -439,6 +439,56 @@
 }
 END_TEST
 
+static void *loop_timer_thread(void *arg)
+{
+	int res;
+	qb_loop_t *l = (qb_loop_t *)arg;
+	qb_loop_timer_handle test_tht;
+
+	res = qb_loop_timer_add(l, QB_LOOP_LOW, 5*QB_TIME_NS_IN_MSEC, l, one_shot_tmo, &test_tht);
+	ck_assert_int_eq(res, 0);
+
+	res = qb_loop_timer_is_running(l, test_th);
+	ck_assert_int_eq(res, QB_TRUE);
+
+	sleep(5);
+
+	return (void *)0;
+}
+
+/* This test will probably never fail (unless something
+   really bad happens) but is useful for running under
+   helgrind to find threading issues */
+START_TEST(test_loop_timer_threads)
+{
+	int32_t res;
+	pthread_t thr;
+	qb_loop_t *l = qb_loop_create();
+	ck_assert(l != NULL);
+
+	res = pthread_create(&thr, NULL, loop_timer_thread, l);
+
+	res = qb_loop_timer_add(l, QB_LOOP_LOW, 7*QB_TIME_NS_IN_MSEC, l, reset_one_shot_tmo, &reset_th);
+	ck_assert_int_eq(res, 0);
+
+	res = qb_loop_timer_add(l, QB_LOOP_HIGH, 20*QB_TIME_NS_IN_MSEC, l, check_time_left, &test_th2);
+	ck_assert_int_eq(res, 0);
+
+	res = qb_loop_timer_add(l, QB_LOOP_LOW, 60*QB_TIME_NS_IN_MSEC, l, job_stop, &test_th);
+	ck_assert_int_eq(res, 0);
+
+	qb_loop_run(l);
+
+	ck_assert_int_eq(reset_timer_step, 2);
+
+	pthread_join(thr, NULL);
+	qb_loop_destroy(l);
+}
+END_TEST
+
+
+
+
 struct qb_stop_watch {
 	uint64_t start;
 	uint64_t end;
@@ -742,6 +792,7 @@
 	add_tcase(s, tc, test_loop_timer_basic, 30);
 	add_tcase(s, tc, test_loop_timer_precision, 30);
 	add_tcase(s, tc, test_loop_timer_expire_leak, 30);
+	add_tcase(s, tc, test_loop_timer_threads, 30);
 
 	return s;
 }
diff -Nru libqb-2.0.2/tests/resources.test libqb-2.0.3/tests/resources.test
--- libqb-2.0.2/tests/resources.test	2020-10-14 11:43:50.000000000 +0200
+++ libqb-2.0.3/tests/resources.test	2021-02-08 12:01:42.000000000 +0100
@@ -1,17 +1,31 @@
 #!/bin/sh
 RETURN=0
+SOCKS_PER_PROCESS=3
 
 IPC_NAME=`cat ipc-test-name 2>/dev/null`
 for d in /dev/shm /var/run $SOCKETDIR; do
-	leftovers=$(find $d -name qb-test*${IPC_NAME}* -size +0c 2>/dev/null | wc -l)
+
+	# Tidy up the deadlock checker sockets first
+	dlocks=$(find $d -name qb-*-test_*dlock*${IPC_NAME}* -size +0c 2>/dev/null)
+	if [ `echo $dlocks|wc -w` -eq $(($SOCKS_PER_PROCESS * 6)) ]; then
+		rm $dlocks
+	elif [ -n "${dlocks}" ]; then
+		echo
+		echo "Error: dlock shared memory segments not closed/unlinked"
+		echo
+		RETURN=1
+	fi
+
+	# Now look for other leftovers
+	leftovers=$(find $d -name qb-*-test_*${IPC_NAME}* -size +0c 2>/dev/null | wc -l)
 	if [ "${leftovers}" -gt 0 ]; then
 		echo
 		echo "Error: shared memory segments not closed/unlinked"
 		echo
 		RETURN=1
 	fi
-	leftovers="$(find $d -name qb-test*${IPC_NAME}* -size 0c 2>/dev/null)"
-	if [ "$(printf '%s\n' "${leftovers}" | wc -l)" -eq 6 ]; then
+	leftovers="$(find $d -name qb-*-test_*${IPC_NAME}* -size 0c 2>/dev/null)"
+	if [ "$(printf '%s\n' "${leftovers}" | wc -l)" -eq $(($SOCKS_PER_PROCESS * 2)) ]; then
 		echo
 		echo "There were some empty leftovers (expected), removing them"
 		echo "${leftovers}" | tee /dev/stderr | xargs rm
diff -Nru libqb-2.0.2/.version libqb-2.0.3/.version
--- libqb-2.0.2/.version	2020-12-03 14:07:31.000000000 +0100
+++ libqb-2.0.3/.version	2021-03-03 09:34:25.000000000 +0100
@@ -1 +1 @@
-2.0.2
+2.0.3

unblock libqb/2.0.3-1
-- 
Thanks,
Feri.

Reply to: