[Debian-ha-commits] [libqb] 01/03: Imported Upstream version 0.17.2

myon at debian.org myon at debian.org
Mon Sep 7 14:34:31 UTC 2015


This is an automated email from the git hooks/post-receive script.

myon pushed a commit to branch master
in repository libqb.

commit 37c156628dfeaec6db4af2dc8d67968be73595d7
Author: Christoph Berg <christoph.berg at credativ.de>
Date:   Mon Sep 7 15:07:05 2015 +0200

    Imported Upstream version 0.17.2
---
 .gitignore                |   2 +
 .travis.yml               |  15 ++-
 README.markdown           |  18 ++--
 configure.ac              |   8 +-
 docs/Makefile.am          |   8 +-
 docs/html.dox.in          |   5 +-
 docs/man.dox.in           |   3 +-
 examples/ipcserver.c      |  36 ++++---
 include/qb/qbatomic.h     |   2 +-
 include/qb/qbipc_common.h |   5 +
 include/qb/qbipcs.h       |   6 +-
 include/qb/qblog.h        |  15 ++-
 include/qb/qbutil.h       |   4 +-
 lib/Makefile.am           |   2 +-
 lib/ipc_int.h             |   2 +-
 lib/ipc_setup.c           | 233 +++++++++++++++++++++++++++++++---------------
 lib/ipc_socket.c          |  54 +++++++++++
 lib/ipcc.c                |   4 +-
 lib/log.c                 | 120 ++++++++++++------------
 lib/log_format.c          |  10 ++
 lib/log_int.h             |  31 ++++++
 lib/loop_poll.c           |   2 +-
 lib/loop_poll_kqueue.c    |  10 +-
 lib/ringbuffer.c          |   4 +-
 lib/unix.c                |  14 +++
 libqb.spec.in             |   5 +-
 tests/check_ipc.c         | 157 ++++++++++++++++++++++++++-----
 tests/check_log.c         |  63 ++++++++++++-
 28 files changed, 622 insertions(+), 216 deletions(-)

diff --git a/.gitignore b/.gitignore
index 23c3507..ae97cf9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
 *.so.*
 *.3
 *.rpm
+*.swp
 *.pc
 *.log
 Makefile
@@ -27,3 +28,4 @@ abi_dumps
 TAGS
 *~
 test-driver
+tests/*.trs
diff --git a/.travis.yml b/.travis.yml
index 42bad2f..eef8bf9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,10 @@
 language: c
 compiler:
   - gcc
-before_install: sudo apt-get install check splint
-install:
- # Deal with issue on Travis builders
- # https://github.com/travis-ci/travis-cookbooks/issues/155
- - "sudo rm -rf /dev/shm && sudo ln -s /run/shm /dev/shm"
+addons:
+        apt:
+                packages:
+                  - check
+                  - splint
 script: ./autogen.sh && ./configure && make check && make distcheck
-notifications:
-  email:
-    recipients:
-      - quarterback-devel at lists.fedorahosted.org
+sudo: false
diff --git a/README.markdown b/README.markdown
index b8bedc0..2f2b130 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,17 +1,18 @@
 # libqb
 
 ## What is libqb?
-libqb is a library with the primary purpose of providing high performance
-client server reusable features. It provides high performance logging,
-tracing, ipc, and poll.
+libqb is a library with the primary purpose of providing high-performance,
+reusable features for client-server architecture, such as logging,
+tracing, inter-process communication (IPC), and polling.
 
-We don't intend be an all encompassing library, but instead provide very
-specially focused APIs that are highly tuned for maximum performance for client/server applications.
+libqb is not intended to be an all-encompassing library, but instead provide
+focused APIs that are highly tuned for maximum performance for client-server
+applications.
 
 [![Build Status](https://travis-ci.org/ClusterLabs/libqb.png)](https://travis-ci.org/ClusterLabs/libqb)
 
-## For more information look at:
-* [Our wiki](https://github.com/clusterlabs/libqb/wiki)
+## For more information, see:
+* [libqb wiki](https://github.com/clusterlabs/libqb/wiki)
 * [Issues/Bugs](https://github.com/clusterlabs/libqb/issues)
 * [The doxygen generated manual](http://clusterlabs.github.io/libqb/0.16.0/doxygen/)
 * You can build it yourself with the following commands:
@@ -42,8 +43,7 @@ If you find this project useful, you may want to consider supporting its future
 There are a number of ways to support the project.
 
 * Test and report issues.
-* Help others on the [mailing list](https://fedorahosted.org/mailman/listinfo/quarterback-devel).
+* Help others on the [developers at clusterlabs.org mailing list](http://clusterlabs.org/mailman/listinfo/developers).
 * Contribute documentation, examples and test cases.
 * Contribute patches.
 * Spread the word.
-
diff --git a/configure.ac b/configure.ac
index a4dc7c0..c8f5e41 100644
--- a/configure.ac
+++ b/configure.ac
@@ -78,7 +78,7 @@ AM_CONDITIONAL(HAVE_SPLINT, test -n "${SPLINT}")
 # args. Global CFLAGS are ignored during this test.
 cc_supports_flag() {
 	BACKUP="$CPPFLAGS"
-	CPPFLAGS="$CPPFLAGS $@"
+	CPPFLAGS="$CPPFLAGS $@ -Werror"
 	AC_MSG_CHECKING([whether $CC supports "$@"])
 	AC_PREPROC_IFELSE([AC_LANG_PROGRAM([])],
 			  [RC=0; AC_MSG_RESULT([yes])],
@@ -253,10 +253,14 @@ case $host_cpu in
 		nongcc_memory_barrier_needed=yes
 		;;
 	arm*)
-		AC_MSG_RESULT([ia64])
+		AC_MSG_RESULT([arm])
 		AC_DEFINE_UNQUOTED([QB_ARCH_ARM], [1], [arm])
 		arch_force_shmlba=yes
 		;;
+	hppa*)
+		AC_MSG_RESULT([hppa])
+		AC_DEFINE_UNQUOTED([QB_ARCH_HPPA], [1], [hppa])
+		;;
 	mips*)
 		AC_MSG_RESULT([ia64])
 		AC_DEFINE_UNQUOTED([QB_ARCH_MIPS], [1], [mips])
diff --git a/docs/Makefile.am b/docs/Makefile.am
index f4b6197..0c6eaa3 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -32,12 +32,12 @@ dist_man_MANS += man3/qbipcc.h.3 man3/qbipcs.h.3 man3/qbatomic.h.3 \
 
 
 $(dist_man_MANS): man.dox $(dependant_headers)
-	@mkdir -p man3
-	@doxygen man.dox
+	mkdir -p man3
+	doxygen man.dox
 
 doxygen: html.dox
-	@mkdir -p html
-	@doxygen html.dox
+	mkdir -p html
+	doxygen html.dox
 
 else
 doxygen:
diff --git a/docs/html.dox.in b/docs/html.dox.in
index abeef17..b477972 100644
--- a/docs/html.dox.in
+++ b/docs/html.dox.in
@@ -32,7 +32,6 @@ IDL_PROPERTY_SUPPORT   = NO
 DISTRIBUTE_GROUP_DOC   = YES
 SUBGROUPING            = NO
 TYPEDEF_HIDES_STRUCT   = YES
-SYMBOL_CACHE_SIZE      = 0
 EXTRACT_ALL            = YES
 EXTRACT_PRIVATE        = NO
 EXTRACT_STATIC         = YES
@@ -108,7 +107,6 @@ HTML_HEADER            =
 HTML_FOOTER            =
 HTML_TIMESTAMP         = NO
 HTML_STYLESHEET        =
-HTML_ALIGN_MEMBERS     = YES
 HTML_DYNAMIC_SECTIONS  = NO
 GENERATE_DOCSET        = NO
 DOCSET_FEEDNAME        = "Doxygen generated docs"
@@ -131,7 +129,6 @@ QHG_LOCATION           =
 DISABLE_INDEX          = NO
 ENUM_VALUES_PER_LINE   = 4
 GENERATE_TREEVIEW      = NO
-USE_INLINE_TREES       = NO
 TREEVIEW_WIDTH         = 250
 FORMULA_FONTSIZE       = 10
 SEARCHENGINE           = YES
@@ -188,7 +185,7 @@ CLASS_DIAGRAMS         = YES
 MSCGEN_PATH            =
 HIDE_UNDOC_RELATIONS   = YES
 HAVE_DOT               = YES
-DOT_FONTNAME           = FreeSans
+DOT_FONTNAME           =
 DOT_FONTSIZE           = 10
 DOT_FONTPATH           =
 CLASS_GRAPH            = YES
diff --git a/docs/man.dox.in b/docs/man.dox.in
index f88e216..1d3c73b 100644
--- a/docs/man.dox.in
+++ b/docs/man.dox.in
@@ -32,7 +32,6 @@ IDL_PROPERTY_SUPPORT   = NO
 DISTRIBUTE_GROUP_DOC   = YES
 SUBGROUPING            = NO
 TYPEDEF_HIDES_STRUCT   = YES
-SYMBOL_CACHE_SIZE      = 0
 EXTRACT_ALL            = YES
 EXTRACT_PRIVATE        = NO
 EXTRACT_STATIC         = YES
@@ -136,7 +135,7 @@ CLASS_DIAGRAMS         = NO
 MSCGEN_PATH            =
 HIDE_UNDOC_RELATIONS   = YES
 HAVE_DOT               = NO
-DOT_FONTNAME           = FreeSans
+DOT_FONTNAME           =
 DOT_FONTSIZE           = 10
 DOT_FONTPATH           =
 CLASS_GRAPH            = NO
diff --git a/examples/ipcserver.c b/examples/ipcserver.c
index 356c038..7514810 100644
--- a/examples/ipcserver.c
+++ b/examples/ipcserver.c
@@ -182,7 +182,7 @@ show_usage(const char *name)
 
 #ifdef HAVE_GLIB
 struct gio_to_qb_poll {
-	gboolean is_used;
+	int32_t is_used;
 	int32_t events;
 	int32_t source;
 	int32_t fd;
@@ -205,14 +205,17 @@ gio_poll_destroy(gpointer data)
 {
 	struct gio_to_qb_poll *adaptor = (struct gio_to_qb_poll *)data;
 
-	qb_log(LOG_DEBUG, "fd %d adaptor destroyed\n", adaptor->fd);
-	adaptor->is_used = QB_FALSE;
-	adaptor->fd = 0;
+	adaptor->is_used--;
+	if (adaptor->is_used == 0) {
+		qb_log(LOG_DEBUG, "fd %d adaptor destroyed\n", adaptor->fd);
+		adaptor->fd = 0;
+		adaptor->source = 0;
+	}
 }
 
 static int32_t
-my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
-		  void *data, qb_ipcs_dispatch_fn_t fn)
+my_g_dispatch_update(enum qb_loop_priority p, int32_t fd, int32_t evts,
+		  void *data, qb_ipcs_dispatch_fn_t fn, gboolean is_new)
 {
 	struct gio_to_qb_poll *adaptor;
 	GIOChannel *channel;
@@ -222,8 +225,12 @@ my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
 	if (res < 0) {
 		return res;
 	}
-	if (adaptor->is_used) {
-		return -EEXIST;
+	if (adaptor->is_used && adaptor->source) {
+		if (is_new) {
+			return -EEXIST;
+		}
+		g_source_remove(adaptor->source);
+		adaptor->source = 0;
 	}
 
 	channel = g_io_channel_unix_new(fd);
@@ -235,7 +242,7 @@ my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
 	adaptor->events = evts;
 	adaptor->data = data;
 	adaptor->p = p;
-	adaptor->is_used = TRUE;
+	adaptor->is_used++;
 	adaptor->fd = fd;
 
 	adaptor->source = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, evts, gio_read_socket, adaptor, gio_poll_destroy);
@@ -248,10 +255,17 @@ my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
 }
 
 static int32_t
+my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
+		  void *data, qb_ipcs_dispatch_fn_t fn)
+{
+	return my_g_dispatch_update(p, fd, evts, data, fn, TRUE);
+}
+
+static int32_t
 my_g_dispatch_mod(enum qb_loop_priority p, int32_t fd, int32_t evts,
 		  void *data, qb_ipcs_dispatch_fn_t fn)
 {
-	return 0;
+	return my_g_dispatch_update(p, fd, evts, data, fn, FALSE);
 }
 
 static int32_t
@@ -260,7 +274,7 @@ my_g_dispatch_del(int32_t fd)
 	struct gio_to_qb_poll *adaptor;
 	if (qb_array_index(gio_map, fd, (void **)&adaptor) == 0) {
 		g_source_remove(adaptor->source);
-		adaptor->is_used = FALSE;
+		adaptor->source = 0;
 	}
 	return 0;
 }
diff --git a/include/qb/qbatomic.h b/include/qb/qbatomic.h
index bd475b4..45c762e 100644
--- a/include/qb/qbatomic.h
+++ b/include/qb/qbatomic.h
@@ -52,7 +52,7 @@ extern "C" {
  * You must not directly read integers or pointers concurrently
  * accessed by multiple threads, but use the atomic accessor functions
  * instead. That is, always use qb_atomic_int_get() and qb_atomic_pointer_get()
- * for read outs. They provide the neccessary synchonization mechanisms
+ * for read outs. They provide the necessary synchonization mechanisms
  * like memory barriers to access memory locations concurrently.
  *
  * If you are using those functions for anything apart from
diff --git a/include/qb/qbipc_common.h b/include/qb/qbipc_common.h
index 0a4118c..2253941 100644
--- a/include/qb/qbipc_common.h
+++ b/include/qb/qbipc_common.h
@@ -31,6 +31,11 @@ extern "C" {
 #endif
 /* *INDENT-ON* */
 
+/**
+ * @file qbipc_common.h
+ * common types and definitions
+ */
+
 struct qb_ipc_request_header {
 	int32_t id __attribute__ ((aligned(8)));
 	int32_t size __attribute__ ((aligned(8)));
diff --git a/include/qb/qbipcs.h b/include/qb/qbipcs.h
index 9ef2aa6..6e6ef85 100644
--- a/include/qb/qbipcs.h
+++ b/include/qb/qbipcs.h
@@ -237,7 +237,7 @@ int32_t qb_ipcs_run(qb_ipcs_service_t* s);
 void qb_ipcs_destroy(qb_ipcs_service_t* s);
 
 /**
- * Limit the incomming request rate.
+ * Limit the incoming request rate.
  * @param s service instance
  * @param rl the new rate
  */
@@ -245,7 +245,7 @@ void qb_ipcs_request_rate_limit(qb_ipcs_service_t* s,
 			       	enum qb_ipcs_rate_limit rl);
 
 /**
- * Send a response to a incomming request.
+ * Send a response to a incoming request.
  *
  * @param c connection instance
  * @param data the message to send
@@ -260,7 +260,7 @@ ssize_t qb_ipcs_response_send(qb_ipcs_connection_t *c, const void *data,
 			      size_t size);
 
 /**
- * Send a response to a incomming request.
+ * Send a response to a incoming request.
  *
  * @param c connection instance
  * @param iov the iovec struct that points to the message to send
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
index 35fcc58..042d7a0 100644
--- a/include/qb/qblog.h
+++ b/include/qb/qblog.h
@@ -363,18 +363,30 @@ void qb_log_from_external_source_va(const char *function,
  */
 #define qb_log(priority, fmt, args...) qb_logt(priority, 0, fmt, ##args)
 
+/* Define the character used to mark the beginning of "extended" information;
+ * a string equivalent is also defined so clients can use it like:
+ *    qb_log(level, "blah blah "QB_XS" yada yada", __func__);
+ */
+#define QB_XC '\a'
+#define QB_XS "\a"
+
 /**
  * This is similar to perror except it goes into the logging system.
  *
  * @param priority this takes syslog priorities.
  * @param fmt usual printf style format specifiers
  * @param args usual printf style args
+ *
+ * @note Because qb_perror() adds the system error message and error number onto
+ *       the end of the given fmt, that information will become extended
+ *       information if QB_XS is used inside fmt and will not show up in any
+ *       logs that strip extended information.
  */
 #ifndef S_SPLINT_S
 #define qb_perror(priority, fmt, args...) do {				\
 	char _perr_buf_[QB_LOG_STRERROR_MAX_LEN];			\
 	const char *_perr_str_ = qb_strerror_r(errno, _perr_buf_, sizeof(_perr_buf_));	\
-	qb_logt(priority, 0, fmt ": %s (%d)", ##args, _perr_str_, errno);		\
+	qb_logt(priority, 0, fmt ": %s (%d)", ##args, _perr_str_, errno); \
     } while(0)
 #else
 #define qb_perror
@@ -405,6 +417,7 @@ enum qb_log_conf {
 	QB_LOG_CONF_PRIORITY_BUMP,
 	QB_LOG_CONF_STATE_GET,
 	QB_LOG_CONF_FILE_SYNC,
+	QB_LOG_CONF_EXTENDED,
 };
 
 enum qb_log_filter_type {
diff --git a/include/qb/qbutil.h b/include/qb/qbutil.h
index 87102e8..bfce349 100644
--- a/include/qb/qbutil.h
+++ b/include/qb/qbutil.h
@@ -36,10 +36,10 @@ extern "C" {
 
 /**
  * @file qbutil.h
- * @author Angus Salkeld <asalkeld at redhat.com>
- *
  * These are some convience functions used throughout libqb.
  *
+ * @author Angus Salkeld <asalkeld at redhat.com>
+ *
  * @par Locking
  * - qb_thread_lock_create()
  * - qb_thread_lock()
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 37b9c23..c153d7e 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -29,7 +29,7 @@ AM_CPPFLAGS             = -I$(top_builddir)/include -I$(top_srcdir)/include
 
 lib_LTLIBRARIES		= libqb.la
 
-libqb_la_LDFLAGS	= -version-number 0:17:1
+libqb_la_LDFLAGS	= -version-info 17:2:17
 
 source_to_lint		= util.c hdb.c ringbuffer.c ringbuffer_helper.c \
 			  array.c loop.c loop_poll.c loop_job.c \
diff --git a/lib/ipc_int.h b/lib/ipc_int.h
index c22417b..500315e 100644
--- a/lib/ipc_int.h
+++ b/lib/ipc_int.h
@@ -159,7 +159,7 @@ enum qb_ipcs_connection_state {
 	QB_IPCS_CONNECTION_SHUTTING_DOWN,
 };
 
-#define CONNECTION_DESCRIPTION (16)
+#define CONNECTION_DESCRIPTION (34) /* INT_MAX length + 3 */
 
 struct qb_ipcs_connection_auth {
 	uid_t uid;
diff --git a/lib/ipc_setup.c b/lib/ipc_setup.c
index 1ea085b..28a0ddc 100644
--- a/lib/ipc_setup.c
+++ b/lib/ipc_setup.c
@@ -48,6 +48,24 @@ struct ipc_auth_ugp {
 	pid_t pid;
 };
 
+struct ipc_auth_data {
+	int32_t sock;
+	struct qb_ipcs_service *s;
+	struct qb_ipc_connection_request msg;
+	struct msghdr msg_recv;
+	struct iovec iov_recv;
+	struct ipc_auth_ugp ugp;
+
+	size_t processed;
+	size_t len;
+
+#ifdef SO_PASSCRED
+	char *cmsg_cred;
+#endif
+
+};
+
+
 static int32_t qb_ipcs_us_connection_acceptor(int fd, int revent, void *data);
 
 ssize_t
@@ -83,20 +101,21 @@ retry_send:
 }
 
 static ssize_t
-qb_ipc_us_recv_msghdr(int32_t s, struct msghdr *hdr, char *msg, size_t len)
+qb_ipc_us_recv_msghdr(struct ipc_auth_data *data)
 {
+	char *msg = (char *) &data->msg;
 	int32_t result;
-	int32_t processed = 0;
 
 	qb_sigpipe_ctl(QB_SIGPIPE_IGNORE);
 
 retry_recv:
-	hdr->msg_iov->iov_base = &msg[processed];
-	hdr->msg_iov->iov_len = len - processed;
+	data->msg_recv.msg_iov->iov_base = &msg[data->processed];
+	data->msg_recv.msg_iov->iov_len = data->len - data->processed;
 
-	result = recvmsg(s, hdr, MSG_NOSIGNAL | MSG_WAITALL);
+	result = recvmsg(data->sock, &data->msg_recv, MSG_NOSIGNAL | MSG_WAITALL);
 	if (result == -1 && errno == EAGAIN) {
-		goto retry_recv;
+		qb_sigpipe_ctl(QB_SIGPIPE_DEFAULT);
+		return -EAGAIN;
 	}
 	if (result == -1) {
 		qb_sigpipe_ctl(QB_SIGPIPE_DEFAULT);
@@ -105,18 +124,18 @@ retry_recv:
 	if (result == 0) {
 		qb_sigpipe_ctl(QB_SIGPIPE_DEFAULT);
 		qb_util_log(LOG_DEBUG,
-			    "recv(fd %d) got 0 bytes assuming ENOTCONN", s);
+			    "recv(fd %d) got 0 bytes assuming ENOTCONN", data->sock);
 		return -ENOTCONN;
 	}
 
-	processed += result;
-	if (processed != len) {
+	data->processed += result;
+	if (data->processed != data->len) {
 		goto retry_recv;
 	}
 	qb_sigpipe_ctl(QB_SIGPIPE_DEFAULT);
-	assert(processed == len);
+	assert(data->processed == data->len);
 
-	return processed;
+	return data->processed;
 }
 
 int32_t
@@ -434,6 +453,7 @@ qb_ipcs_us_withdraw(struct qb_ipcs_service * s)
 	(void)s->poll_fns.dispatch_del(s->server_sock);
 	shutdown(s->server_sock, SHUT_RDWR);
 	close(s->server_sock);
+	s->server_sock = -1;
 	return 0;
 }
 
@@ -541,45 +561,56 @@ send_response:
 	return res;
 }
 
-static int32_t
-qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
-			 struct ipc_auth_ugp *ugp)
+static void
+destroy_ipc_auth_data(struct ipc_auth_data *data)
 {
-	int32_t res = 0;
-	struct msghdr msg_recv;
-	struct iovec iov_recv;
+	if (data->s) {
+		qb_ipcs_unref(data->s);
+	}
 
 #ifdef SO_PASSCRED
-	char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))];
-	int off = 0;
-	int on = 1;
-#endif
-	msg_recv.msg_iov = &iov_recv;
-	msg_recv.msg_iovlen = 1;
-	msg_recv.msg_name = 0;
-	msg_recv.msg_namelen = 0;
-#ifdef SO_PASSCRED
-	msg_recv.msg_control = (void *)cmsg_cred;
-	msg_recv.msg_controllen = sizeof(cmsg_cred);
+	free(data->cmsg_cred);
 #endif
-#ifdef QB_SOLARIS
-	msg_recv.msg_accrights = 0;
-	msg_recv.msg_accrightslen = 0;
-#else
-	msg_recv.msg_flags = 0;
-#endif /* QB_SOLARIS */
+	free(data);
+}
+
+static int32_t
+process_auth(int32_t fd, int32_t revents, void *d)
+{
+	struct ipc_auth_data *data = (struct ipc_auth_data *) d;
 
-	iov_recv.iov_base = msg;
-	iov_recv.iov_len = len;
+	int32_t res = 0;
 #ifdef SO_PASSCRED
-	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+	int off = 0;
 #endif
 
-	res = qb_ipc_us_recv_msghdr(sock, &msg_recv, msg, len);
-	if (res < 0) {
+	if (data->s->server_sock == -1) {
+		qb_util_log(LOG_DEBUG, "Closing fd (%d) for server shutdown", fd);
+		res = -ESHUTDOWN;
 		goto cleanup_and_return;
 	}
-	if (res != len) {
+
+	if (revents & POLLNVAL) {
+		qb_util_log(LOG_DEBUG, "NVAL conn fd (%d)", fd);
+		res = -EINVAL;
+		goto cleanup_and_return;
+	}
+	if (revents & POLLHUP) {
+		qb_util_log(LOG_DEBUG, "HUP conn fd (%d)", fd);
+		res = -ESHUTDOWN;
+		goto cleanup_and_return;
+	}
+	if ((revents & POLLIN) == 0) {
+		return 0;
+	}
+
+	res = qb_ipc_us_recv_msghdr(data);
+	if (res == -EAGAIN) {
+		/* yield to mainloop, Let mainloop call us again */
+		return 0;
+	}
+
+	if (res != data->len) {
 		res = -EIO;
 		goto cleanup_and_return;
 	}
@@ -595,11 +626,11 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
 	{
 		ucred_t *uc = NULL;
 
-		if (getpeerucred(sock, &uc) == 0) {
+		if (getpeerucred(data->sock, &uc) == 0) {
 			res = 0;
-			ugp->uid = ucred_geteuid(uc);
-			ugp->gid = ucred_getegid(uc);
-			ugp->pid = ucred_getpid(uc);
+			data->ugp.uid = ucred_geteuid(uc);
+			data->ugp.gid = ucred_getegid(uc);
+			data->ugp.pid = ucred_getpid(uc);
 			ucred_free(uc);
 		} else {
 			res = -errno;
@@ -614,7 +645,7 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
 		 * TODO get the peer's pid.
 		 * c->pid = ?;
 		 */
-		if (getpeereid(sock, &ugp->uid, &ugp->gid) == 0) {
+		if (getpeereid(data->sock, &data->ugp.uid, &data->ugp.gid) == 0) {
 			res = 0;
 		} else {
 			res = -errno;
@@ -630,33 +661,105 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
 		struct cmsghdr *cmsg;
 
 		res = -EINVAL;
-		for (cmsg = CMSG_FIRSTHDR(&msg_recv); cmsg != NULL;
-		     cmsg = CMSG_NXTHDR(&msg_recv, cmsg)) {
+		for (cmsg = CMSG_FIRSTHDR(&data->msg_recv); cmsg != NULL;
+		     cmsg = CMSG_NXTHDR(&data->msg_recv, cmsg)) {
 			if (cmsg->cmsg_type != SCM_CREDENTIALS)
 				continue;
 
 			memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
 			res = 0;
-			ugp->pid = cred.pid;
-			ugp->uid = cred.uid;
-			ugp->gid = cred.gid;
+			data->ugp.pid = cred.pid;
+			data->ugp.uid = cred.uid;
+			data->ugp.gid = cred.gid;
 			break;
 		}
 	}
 #else /* no credentials */
-	ugp->pid = 0;
-	ugp->uid = 0;
-	ugp->gid = 0;
+	data->ugp.pid = 0;
+	data->ugp.uid = 0;
+	data->ugp.gid = 0;
 	res = -ENOTSUP;
 #endif /* no credentials */
 
 cleanup_and_return:
+#ifdef SO_PASSCRED
+	setsockopt(data->sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
+#endif
 
+	(void)data->s->poll_fns.dispatch_del(data->sock);
+
+	if (res < 0) {
+		close(data->sock);
+	} else if (data->msg.hdr.id == QB_IPC_MSG_AUTHENTICATE) {
+		(void)handle_new_connection(data->s, res, data->sock, &data->msg, data->len, &data->ugp);
+	} else {
+		close(data->sock);
+	}
+	destroy_ipc_auth_data(data);
+
+	return 1;
+}
+
+static void
+qb_ipcs_uc_recv_and_auth(int32_t sock, struct qb_ipcs_service *s)
+{
+	int res = 0;
+	struct ipc_auth_data *data = NULL;
 #ifdef SO_PASSCRED
-	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
+	int on = 1;
 #endif
 
-	return res;
+	data = calloc(1, sizeof(struct ipc_auth_data));
+	if (data == NULL) {
+		close(sock);
+		/* -ENOMEM */
+		return;
+	}
+
+	data->s = s;
+	qb_ipcs_ref(data->s);
+
+	data->msg_recv.msg_iov = &data->iov_recv;
+	data->msg_recv.msg_iovlen = 1;
+	data->msg_recv.msg_name = 0;
+	data->msg_recv.msg_namelen = 0;
+
+#ifdef SO_PASSCRED
+	data->cmsg_cred = calloc(1,CMSG_SPACE(sizeof(struct ucred)));
+	if (data->cmsg_cred == NULL) {
+		close(sock);
+		destroy_ipc_auth_data(data);
+		/* -ENOMEM */
+		return;
+	}
+	data->msg_recv.msg_control = (void *)data->cmsg_cred;
+	data->msg_recv.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
+#endif
+#ifdef QB_SOLARIS
+	data->msg_recv.msg_accrights = 0;
+	data->msg_recv.msg_accrightslen = 0;
+#else
+	data->msg_recv.msg_flags = 0;
+#endif /* QB_SOLARIS */
+
+	data->len = sizeof(struct qb_ipc_connection_request);
+	data->iov_recv.iov_base = &data->msg;
+	data->iov_recv.iov_len = data->len;
+	data->sock = sock;
+
+#ifdef SO_PASSCRED
+	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+#endif
+
+	res = s->poll_fns.dispatch_add(QB_LOOP_MED,
+					data->sock,
+					POLLIN | POLLPRI | POLLNVAL,
+					data, process_auth);
+	if (res < 0) {
+		qb_util_log(LOG_DEBUG, "Failed to process AUTH for fd (%d)", data->sock);
+		close(sock);
+		destroy_ipc_auth_data(data);
+	}
 }
 
 static int32_t
@@ -666,8 +769,6 @@ qb_ipcs_us_connection_acceptor(int fd, int revent, void *data)
 	int32_t new_fd;
 	struct qb_ipcs_service *s = (struct qb_ipcs_service *)data;
 	int32_t res;
-	struct qb_ipc_connection_request setup_msg;
-	struct ipc_auth_ugp ugp;
 	socklen_t addrlen = sizeof(struct sockaddr_un);
 
 	if (revent & (POLLNVAL | POLLHUP | POLLERR)) {
@@ -707,22 +808,6 @@ retry_accept:
 		return 0;
 	}
 
-	res = qb_ipcs_uc_recv_and_auth(new_fd, &setup_msg, sizeof(setup_msg),
-				       &ugp);
-	if (res < 0) {
-		close(new_fd);
-		/* This is an error, but -1 would indicate disconnect
-		 * from the poll loop
-		 */
-		return 0;
-	}
-
-	if (setup_msg.hdr.id == QB_IPC_MSG_AUTHENTICATE) {
-		(void)handle_new_connection(s, res, new_fd, &setup_msg,
-					    sizeof(setup_msg), &ugp);
-	} else {
-		close(new_fd);
-	}
-
+	qb_ipcs_uc_recv_and_auth(new_fd, s);
 	return 0;
 }
diff --git a/lib/ipc_socket.c b/lib/ipc_socket.c
index 8fab48f..ef97041 100644
--- a/lib/ipc_socket.c
+++ b/lib/ipc_socket.c
@@ -287,8 +287,36 @@ _finish_connecting(struct qb_ipc_one_way *one_way)
 static void
 qb_ipcc_us_disconnect(struct qb_ipcc_connection *c)
 {
+#if !(defined(QB_LINUX) || defined(QB_CYGWIN))
+  struct sockaddr_un un_addr;
+  socklen_t un_addr_len = sizeof(struct sockaddr_un);
+  char *base_name;
+  char sock_name[PATH_MAX];
+  size_t length;
+#endif
+
 	munmap(c->request.u.us.shared_data, SHM_CONTROL_SIZE);
 	unlink(c->request.u.us.shared_file_name);
+
+#if !(defined(QB_LINUX) || defined(QB_CYGWIN))
+    if (getsockname(c->response.u.us.sock, (struct sockaddr *)&un_addr, &un_addr_len) == 0) {
+      length = strlen(un_addr.sun_path);
+      base_name = strndup(un_addr.sun_path,length-8);
+      qb_util_log(LOG_DEBUG, "unlinking socket bound files with base_name=%s length=%d",base_name,length);
+      snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"request");
+      qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
+      unlink(sock_name);
+      snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"event");
+      qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
+      unlink(sock_name);
+      snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"event-tx");
+      qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
+      unlink(sock_name);
+      snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"response");
+      qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
+      unlink(sock_name);
+    }
+#endif
 	qb_ipcc_us_sock_close(c->event.u.us.sock);
 	qb_ipcc_us_sock_close(c->request.u.us.sock);
 	qb_ipcc_us_sock_close(c->setup.u.us.sock);
@@ -629,12 +657,38 @@ _sock_rm_from_mainloop(struct qb_ipcs_connection *c)
 static void
 qb_ipcs_us_disconnect(struct qb_ipcs_connection *c)
 {
+#if !(defined(QB_LINUX) || defined(QB_CYGWIN))
+	struct sockaddr_un un_addr;
+	socklen_t un_addr_len = sizeof(struct sockaddr_un);
+	char *base_name;
+	char sock_name[PATH_MAX];
+	size_t length;
+#endif
 	qb_enter();
 
 	if (c->state == QB_IPCS_CONNECTION_ESTABLISHED ||
 	    c->state == QB_IPCS_CONNECTION_ACTIVE) {
 		_sock_rm_from_mainloop(c);
 
+#if !(defined(QB_LINUX) || defined(QB_CYGWIN))
+		if (getsockname(c->response.u.us.sock, (struct sockaddr *)&un_addr, &un_addr_len) == 0) {
+			length = strlen(un_addr.sun_path);
+			base_name = strndup(un_addr.sun_path,length-8);
+			qb_util_log(LOG_DEBUG, "unlinking socket bound files with base_name=%s length=%d",base_name,length);
+			snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"request");
+			qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
+			unlink(sock_name);
+			snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"event");
+			qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
+			unlink(sock_name);
+			snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"event-tx");
+			qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
+			unlink(sock_name);
+			snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"response");
+			qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
+			unlink(sock_name);
+		}
+#endif
 		qb_ipcc_us_sock_close(c->setup.u.us.sock);
 		qb_ipcc_us_sock_close(c->request.u.us.sock);
 		qb_ipcc_us_sock_close(c->event.u.us.sock);
diff --git a/lib/ipcc.c b/lib/ipcc.c
index f9042c8..77ec3c3 100644
--- a/lib/ipcc.c
+++ b/lib/ipcc.c
@@ -81,7 +81,9 @@ qb_ipcc_connect(const char *name, size_t max_msg_size)
 	return c;
 
 disconnect_and_cleanup:
-	qb_ipcc_us_sock_close(c->setup.u.us.sock);
+	if (c->setup.u.us.sock >= 0) {
+		qb_ipcc_us_sock_close(c->setup.u.us.sock);
+	}
 	free(c->receive_buf);
 	free(c);
 	errno = -res;
diff --git a/lib/log.c b/lib/log.c
index 142c2f7..9808c63 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -29,6 +29,7 @@
 #include <dlfcn.h>
 #endif /* HAVE_DLFCN_H */
 #include <stdarg.h>
+#include <string.h>
 
 #include <qb/qbdefs.h>
 #include <qb/qblist.h>
@@ -157,14 +158,38 @@ _cs_matches_filter_(struct qb_log_callsite *cs,
 	return match;
 }
 
+/**
+ * @internal
+ * @brief Format a log message into a string buffer
+ *
+ * @param[out] str  Destination buffer to contain formatted string
+ * @param[in]  cs   Callsite containing format to use
+ * @param[in]  ap   Variable arguments for format
+ */
+static inline void
+cs_format(char *str, struct qb_log_callsite *cs, va_list ap)
+{
+	va_list ap_copy;
+	int len;
+
+	va_copy(ap_copy, ap);
+	len = vsnprintf(str, QB_LOG_MAX_LEN, cs->format, ap_copy);
+	va_end(ap_copy);
+	if (len > QB_LOG_MAX_LEN) {
+		len = QB_LOG_MAX_LEN;
+	}
+	if (str[len - 1] == '\n') {
+		str[len - 1] = '\0';
+	}
+}
+
 void
 qb_log_real_va_(struct qb_log_callsite *cs, va_list ap)
 {
-	int32_t found_threaded;
+	int32_t found_threaded = QB_FALSE;
 	struct qb_log_target *t;
 	struct timespec tv;
 	int32_t pos;
-	int len;
 	int32_t formatted = QB_FALSE;
 	char buf[QB_LOG_MAX_LEN];
 	char *str = buf;
@@ -175,20 +200,15 @@ qb_log_real_va_(struct qb_log_callsite *cs, va_list ap)
 	}
 	in_logger = QB_TRUE;
 
-	if (old_internal_log_fn) {
-		if (qb_bit_is_set(cs->tags, QB_LOG_TAG_LIBQB_MSG_BIT)) {
-			if (!formatted) {
-				va_copy(ap_copy, ap);
-				len = vsnprintf(str, QB_LOG_MAX_LEN, cs->format, ap_copy);
-				va_end(ap_copy);
-				if (len > QB_LOG_MAX_LEN)
-					len = QB_LOG_MAX_LEN;
-				if (str[len - 1] == '\n') str[len - 1] = '\0';
-				formatted = QB_TRUE;
-			}
-			old_internal_log_fn(cs->filename, cs->lineno,
-					    cs->priority, str);
+	if (old_internal_log_fn &&
+	    qb_bit_is_set(cs->tags, QB_LOG_TAG_LIBQB_MSG_BIT)) {
+		if (formatted == QB_FALSE) {
+			cs_format(str, cs, ap);
+			formatted = QB_TRUE;
 		}
+		qb_do_extended(str, QB_TRUE,
+			old_internal_log_fn(cs->filename, cs->lineno,
+					    cs->priority, str));
 	}
 
 	qb_util_timespec_from_epoch_get(&tv);
@@ -197,45 +217,31 @@ qb_log_real_va_(struct qb_log_callsite *cs, va_list ap)
 	 * 1 if we can find a threaded target that needs this log then post it
 	 * 2 foreach non-threaded target call it's logger function
 	 */
-	found_threaded = QB_FALSE;
-
 	for (pos = 0; pos <= conf_active_max; pos++) {
 		t = &conf[pos];
-		if (t->state != QB_LOG_STATE_ENABLED) {
-			continue;
-		}
-		if (t->threaded) {
-			if (!found_threaded
-			    && qb_bit_is_set(cs->targets, t->pos)) {
-				found_threaded = QB_TRUE;
-				if (!formatted) {
-					va_copy(ap_copy, ap);
-					len = vsnprintf(str, QB_LOG_MAX_LEN, cs->format, ap_copy);
-					va_end(ap_copy);
-					if (len > QB_LOG_MAX_LEN)
-						len = QB_LOG_MAX_LEN;
-					if (str[len - 1] == '\n') str[len - 1] = '\0';
-					formatted = QB_TRUE;
-				}
-			}
-		} else {
-			if (qb_bit_is_set(cs->targets, t->pos)) {
-				if (t->vlogger) {
-					va_copy(ap_copy, ap);
-					t->vlogger(t->pos, cs, tv.tv_sec, ap_copy);
-					va_end(ap_copy);
-				} else if (t->logger) {
-					if (!formatted) {
-						va_copy(ap_copy, ap);
-						len = vsnprintf(str, QB_LOG_MAX_LEN, cs->format, ap_copy);
-						va_end(ap_copy);
-						if (len > QB_LOG_MAX_LEN)
-							len = QB_LOG_MAX_LEN;
-						if (str[len - 1] == '\n') str[len - 1] = '\0';
+		if ((t->state == QB_LOG_STATE_ENABLED)
+		    && qb_bit_is_set(cs->targets, pos)) {
+			if (t->threaded) {
+				if (!found_threaded) {
+					found_threaded = QB_TRUE;
+					if (formatted == QB_FALSE) {
+						cs_format(str, cs, ap);
 						formatted = QB_TRUE;
 					}
-					t->logger(t->pos, cs, tv.tv_sec, str);
 				}
+
+			} else if (t->vlogger) {
+				va_copy(ap_copy, ap);
+				t->vlogger(t->pos, cs, tv.tv_sec, ap_copy);
+				va_end(ap_copy);
+
+			} else if (t->logger) {
+				if (formatted == QB_FALSE) {
+					cs_format(str, cs, ap);
+					formatted = QB_TRUE;
+				}
+				qb_do_extended(str, t->extended,
+					       t->logger(t->pos, cs, tv.tv_sec, str));
 			}
 		}
 	}
@@ -265,14 +271,10 @@ qb_log_thread_log_write(struct qb_log_callsite *cs,
 
 	for (pos = 0; pos <= conf_active_max; pos++) {
 		t = &conf[pos];
-		if (t->state != QB_LOG_STATE_ENABLED) {
-			continue;
-		}
-		if (!t->threaded) {
-			continue;
-		}
-		if (qb_bit_is_set(cs->targets, t->pos)) {
-			t->logger(t->pos, cs, timestamp, buffer);
+		if ((t->state == QB_LOG_STATE_ENABLED) && t->threaded
+		    && qb_bit_is_set(cs->targets, t->pos)) {
+			qb_do_extended(buffer, t->extended,
+				t->logger(t->pos, cs, timestamp, buffer));
 		}
 	}
 }
@@ -810,6 +812,7 @@ qb_log_init(const char *name, int32_t facility, uint8_t priority)
 		conf[i].pos = i;
 		conf[i].debug = QB_FALSE;
 		conf[i].file_sync = QB_FALSE;
+		conf[i].extended = QB_TRUE;
 		conf[i].state = QB_LOG_STATE_UNUSED;
 		(void)strlcpy(conf[i].name, name, PATH_MAX);
 		conf[i].facility = facility;
@@ -1064,6 +1067,9 @@ qb_log_ctl(int32_t t, enum qb_log_conf c, int32_t arg)
 	case QB_LOG_CONF_THREADED:
 		conf[t].threaded = arg;
 		break;
+	case QB_LOG_CONF_EXTENDED:
+		conf[t].extended = arg;
+		break;
 
 	default:
 		rc = -EINVAL;
diff --git a/lib/log_format.c b/lib/log_format.c
index a8b3239..6c29f0a 100644
--- a/lib/log_format.c
+++ b/lib/log_format.c
@@ -460,12 +460,22 @@ qb_vsnprintf_serialize(char *serialize, size_t max_len,
 {
 	char *format;
 	char *p;
+	char *qb_xc;
 	int type_long = QB_FALSE;
 	int type_longlong = QB_FALSE;
         int sformat_length = 0;
         int sformat_precision = QB_FALSE;
 	uint32_t location = my_strlcpy(serialize, fmt, max_len) + 1;
 
+	/* Assume serialized output always wants extended information
+	 * (@todo: add variant of this function that takes argument for whether
+	 * to print extended information, and make this a macro with that
+	 * argument set to QB_TRUE, so callers can honor extended setting)
+	 */
+	if ((qb_xc = strchr(serialize, QB_XC)) != NULL) {
+		*qb_xc = *(qb_xc + 1)? '|' : '\0';
+	}
+
 	format = (char *)fmt;
 	for (;;) {
 		type_long = QB_FALSE;
diff --git a/lib/log_int.h b/lib/log_int.h
index e25c621..0b295ee 100644
--- a/lib/log_int.h
+++ b/lib/log_int.h
@@ -38,6 +38,7 @@ struct qb_log_target {
 	int32_t priority_bump;
 	int32_t file_sync;
 	int32_t debug;
+	int32_t extended;
 	size_t size;
 	char *format;
 	int32_t threaded;
@@ -70,6 +71,36 @@ struct qb_log_record {
 
 #define TIME_STRING_SIZE 64
 
+/**
+ * @internal
+ * @brief Call a log function, handling any extended information marker
+ *
+ * If the string to be passed to the log function contains an extended
+ * information marker, temporarily modify the string to strip the extended
+ * information if appropriate. Special cases: if a marker occurs with nothing
+ * after it, it will always be stripped; if only extended information is
+ * present, stmt will be called only if extended is true.
+ *
+ * @param[in]  str       Null-terminated log message
+ * @param[in]  extended  QB_TRUE if extended information should be printed
+ * @param[in]  stmt      Code block to call log function
+ *
+ * @note Because this is a macro, none of the arguments other than stmt should
+ *       have side effects.
+ */
+#define qb_do_extended(str, extended, stmt) do { \
+	char *qb_xc = strchr((str), QB_XC); \
+	if (qb_xc) { \
+		if ((qb_xc != (str)) || (extended)) { \
+			*qb_xc = ((extended) && *(qb_xc + 1))? '|' : '\0'; \
+			stmt; \
+			*qb_xc = QB_XC; \
+		} \
+	} else { \
+		stmt; \
+	} \
+} while (0)
+
 struct qb_log_target * qb_log_target_alloc(void);
 void qb_log_target_free(struct qb_log_target *t);
 struct qb_log_target * qb_log_target_get(int32_t pos);
diff --git a/lib/loop_poll.c b/lib/loop_poll.c
index 49c9650..117a276 100644
--- a/lib/loop_poll.c
+++ b/lib/loop_poll.c
@@ -110,7 +110,7 @@ _poll_dispatch_and_take_back_(struct qb_loop_item *item,
 				   pe->item.user_data);
 	if (res < 0) {
 		_poll_entry_mark_deleted_(pe);
-	} else {
+	} else if (pe->state != QB_POLL_ENTRY_DELETED) {
 		pe->state = QB_POLL_ENTRY_ACTIVE;
 		pe->ufd.revents = 0;
 	}
diff --git a/lib/loop_poll_kqueue.c b/lib/loop_poll_kqueue.c
index 871e4b0..898c57d 100644
--- a/lib/loop_poll_kqueue.c
+++ b/lib/loop_poll_kqueue.c
@@ -55,7 +55,7 @@ _add(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t eve
 	struct kevent ke;
 	short filters = _poll_to_filter_(events);
 
-	EV_SET(&ke, fd, filters, EV_ADD | EV_ENABLE, 0, 0, (intptr_t)pe);
+	EV_SET(&ke, fd, filters, EV_ADD | EV_ENABLE, 0, 0, pe);
 
 	res = kevent(s->epollfd, &ke, 1, NULL, 0, NULL);
 	if (res == -1) {
@@ -74,8 +74,8 @@ _mod(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t eve
 	short new_filters = _poll_to_filter_(events);
 	short old_filters = _poll_to_filter_(pe->ufd.events);
 
-	EV_SET(&ke[0], fd, old_filters, EV_DELETE, 0, 0, (intptr_t)pe);
-	EV_SET(&ke[1], fd, new_filters, EV_ADD | EV_ENABLE, 0, 0, (intptr_t)pe);
+	EV_SET(&ke[0], fd, old_filters, EV_DELETE, 0, 0, pe);
+	EV_SET(&ke[1], fd, new_filters, EV_ADD | EV_ENABLE, 0, 0, pe);
 
 	res = kevent(s->epollfd, ke, 2, NULL, 0, NULL);
 	if (res == -1) {
@@ -92,7 +92,7 @@ _del(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t eve
 	struct kevent ke;
 	short filters = _poll_to_filter_(events);
 
-	EV_SET(&ke, fd, filters, EV_DELETE, 0, 0, (intptr_t)pe);
+	EV_SET(&ke, fd, filters, EV_DELETE, 0, 0, pe);
 
 	res = kevent(s->epollfd, &ke, 1, NULL, 0, NULL);
 	if (res == -1 && errno == ENOENT) {
@@ -170,7 +170,7 @@ retry_poll:
 			 * empty/deleted
 			 */
 			EV_SET(&events[i], events[i].ident, events[i].filter,
-			       EV_DELETE, 0, 0, (intptr_t)pe);
+			       EV_DELETE, 0, 0, pe);
 			(void)kevent(s->epollfd, &events[i], 1, NULL, 0, NULL);
 			continue;
 		}
diff --git a/lib/ringbuffer.c b/lib/ringbuffer.c
index f6b1971..db842ce 100644
--- a/lib/ringbuffer.c
+++ b/lib/ringbuffer.c
@@ -138,7 +138,9 @@ qb_rb_open_2(const char *name, size_t size, uint32_t flags,
 	void *shm_addr;
 	long page_size = sysconf(_SC_PAGESIZE);
 
-#ifdef QB_FORCE_SHM_ALIGN
+#ifdef QB_ARCH_HPPA
+	page_size = QB_MAX(page_size, 0x00400000); /* align to page colour */
+#elif defined(QB_FORCE_SHM_ALIGN)
 	page_size = QB_MAX(page_size, 16 * 1024);
 #endif /* QB_FORCE_SHM_ALIGN */
 	/* The user of this api expects the 'size' parameter passed into this function
diff --git a/lib/unix.c b/lib/unix.c
index 79ed538..3ce61bc 100644
--- a/lib/unix.c
+++ b/lib/unix.c
@@ -170,6 +170,19 @@ qb_sys_circular_mmap(int32_t fd, void **buf, size_t bytes)
 	flags |= MAP_PRIVATE;
 #endif /* QB_FORCE_SHM_ALIGN */
 
+#if defined(QB_ARCH_HPPA)
+	/* map twice the size we want to make sure we have already mapped
+	   the second memory location behind it too. Otherwise the Linux
+	   kernel may map it in the upper memory so that we can't map
+	   the second part afterwards since it will conflict. */
+	addr = mmap(NULL, 2*bytes, PROT_READ | PROT_WRITE,
+		    MAP_SHARED, fd, 0);
+
+	if (addr == MAP_FAILED)
+		return -errno;
+
+	addr_orig = addr;
+#else
 	addr_orig = mmap(NULL, bytes << 1, PROT_NONE, flags, -1, 0);
 
 	if (addr_orig == MAP_FAILED) {
@@ -178,6 +191,7 @@ qb_sys_circular_mmap(int32_t fd, void **buf, size_t bytes)
 
 	addr = mmap(addr_orig, bytes, PROT_READ | PROT_WRITE,
 		    MAP_FIXED | MAP_SHARED, fd, 0);
+#endif
 
 	if (addr != addr_orig) {
 		res = -errno;
diff --git a/libqb.spec.in b/libqb.spec.in
index 2d904f6..1e42ac5 100644
--- a/libqb.spec.in
+++ b/libqb.spec.in
@@ -16,8 +16,9 @@ BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires:  autoconf automake libtool doxygen procps check-devel
 
 %description
-libqb provides high performance client server reusable features.
-Initially these are IPC and poll.
+libqb provides high-performance, reusable features for client-server
+architecture, such as logging, tracing, inter-process communication (IPC),
+and polling.
 
 %prep
 %setup -q -n %{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}
diff --git a/tests/check_ipc.c b/tests/check_ipc.c
index ce9a7c0..4397963 100644
--- a/tests/check_ipc.c
+++ b/tests/check_ipc.c
@@ -32,7 +32,7 @@
 #include <qb/qbipcs.h>
 #include <qb/qbloop.h>
 
-static const char *ipc_name = "ipc_test";
+static char ipc_name[256];
 
 #define DEFAULT_MAX_MSG_SIZE (8192*16)
 static int CALCULATED_DGRAM_MAX_MSG_SIZE = 0;
@@ -94,6 +94,7 @@ static int32_t disconnect_after_created = QB_FALSE;
 static int32_t num_bulk_events = 10;
 static int32_t num_stress_events = 30000;
 static int32_t reference_count_test = QB_FALSE;
+static int32_t multiple_connections = QB_FALSE;
 
 
 static int32_t
@@ -104,6 +105,18 @@ exit_handler(int32_t rsignal, void *data)
 	return -1;
 }
 
+static void
+set_ipc_name(const char *prefix)
+{
+	/* We have to give the server name a random postfix because
+	 * some build systems attempt to generate packages for libqb
+	 * in parallel. These unit tests are run during the package
+	 * build process. Two builds executing on the same machine
+	 * can stomp on each other's unit tests if the ipc server
+	 * names aren't unique... This was very confusing to debug */
+	snprintf(ipc_name, 256, "%s-%d", prefix, (int32_t)random());
+}
+
 static int32_t
 s1_msg_process_fn(qb_ipcs_connection_t *c,
 		void *data, size_t size)
@@ -227,6 +240,7 @@ s1_msg_process_fn(qb_ipcs_connection_t *c,
 	} else if (req_pt->id == IPC_MSG_REQ_SERVER_FAIL) {
 		exit(0);
 	} else if (req_pt->id == IPC_MSG_REQ_SERVER_DISCONNECT) {
+		multiple_connections = QB_FALSE;
 		qb_ipcs_disconnect(c);
 	}
 	return 0;
@@ -263,6 +277,9 @@ my_dispatch_del(int32_t fd)
 static int32_t
 s1_connection_closed(qb_ipcs_connection_t *c)
 {
+	if (multiple_connections) {
+		return 0;
+	}
 	qb_enter();
 	qb_leave();
 	return 0;
@@ -301,6 +318,10 @@ outq_flush (void *data)
 static void
 s1_connection_destroyed(qb_ipcs_connection_t *c)
 {
+	if (multiple_connections) {
+		return;
+	}
+
 	qb_enter();
 	if (reference_count_test) {
 		struct cs_ipcs_conn_context *cnx;
@@ -316,6 +337,9 @@ static void
 s1_connection_created(qb_ipcs_connection_t *c)
 {
 	uint32_t max = MAX_MSG_SIZE;
+	if (multiple_connections) {
+		return;
+	}
 
 	if (send_event_on_created) {
 		struct qb_ipc_response_header response;
@@ -698,7 +722,7 @@ START_TEST(test_ipc_exit_us)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	recv_timeout = 5000;
 	test_ipc_exit();
 	qb_leave();
@@ -709,7 +733,7 @@ START_TEST(test_ipc_exit_shm)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	recv_timeout = 1000;
 	test_ipc_exit();
 	qb_leave();
@@ -720,7 +744,7 @@ START_TEST(test_ipc_txrx_shm_timeout)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_txrx_timeout();
 	qb_leave();
 }
@@ -730,7 +754,7 @@ START_TEST(test_ipc_txrx_us_timeout)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_txrx_timeout();
 	qb_leave();
 }
@@ -741,7 +765,7 @@ START_TEST(test_ipc_txrx_shm_tmo)
 	qb_enter();
 	turn_on_fc = QB_FALSE;
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	recv_timeout = 1000;
 	test_ipc_txrx();
 	qb_leave();
@@ -753,7 +777,7 @@ START_TEST(test_ipc_txrx_shm_block)
 	qb_enter();
 	turn_on_fc = QB_FALSE;
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	recv_timeout = -1;
 	test_ipc_txrx();
 	qb_leave();
@@ -766,7 +790,7 @@ START_TEST(test_ipc_fc_shm)
 	turn_on_fc = QB_TRUE;
 	ipc_type = QB_IPC_SHM;
 	recv_timeout = 500;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_txrx();
 	qb_leave();
 }
@@ -777,7 +801,7 @@ START_TEST(test_ipc_txrx_us_block)
 	qb_enter();
 	turn_on_fc = QB_FALSE;
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	recv_timeout = -1;
 	test_ipc_txrx();
 	qb_leave();
@@ -789,7 +813,7 @@ START_TEST(test_ipc_txrx_us_tmo)
 	qb_enter();
 	turn_on_fc = QB_FALSE;
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	recv_timeout = 1000;
 	test_ipc_txrx();
 	qb_leave();
@@ -802,7 +826,7 @@ START_TEST(test_ipc_fc_us)
 	turn_on_fc = QB_TRUE;
 	ipc_type = QB_IPC_SOCKET;
 	recv_timeout = 500;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_txrx();
 	qb_leave();
 }
@@ -857,7 +881,7 @@ START_TEST(test_ipc_disp_us)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_dispatch();
 	qb_leave();
 }
@@ -934,6 +958,60 @@ count_bulk_events(int32_t fd, int32_t revents, void *data)
 }
 
 static void
+test_ipc_stress_connections(void)
+{
+	int32_t c = 0;
+	int32_t j = 0;
+	uint32_t max_size = MAX_MSG_SIZE;
+	int32_t connections = 0;
+	pid_t pid;
+
+	multiple_connections = QB_TRUE;
+
+	qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_CLEAR_ALL,
+			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
+	qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
+			  QB_LOG_FILTER_FILE, "*", LOG_INFO);
+	qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
+
+	pid = run_function_in_new_process(run_ipc_server);
+	fail_if(pid == -1);
+	sleep(1);
+
+	for (connections = 1; connections < 70000; connections++) {
+		if (conn) {
+			qb_ipcc_disconnect(conn);
+			conn = NULL;
+		}
+		do {
+			conn = qb_ipcc_connect(ipc_name, max_size);
+			if (conn == NULL) {
+				j = waitpid(pid, NULL, WNOHANG);
+				ck_assert_int_eq(j, 0);
+				sleep(1);
+				c++;
+			}
+		} while (conn == NULL && c < 5);
+		fail_if(conn == NULL);
+		
+		if (((connections+1) % 1000) == 0) {
+			qb_log(LOG_INFO, "%d ipc connections made", connections+1);
+		}
+	}
+	multiple_connections = QB_FALSE;
+
+	request_server_exit();
+	verify_graceful_stop(pid);
+	qb_ipcc_disconnect(conn);
+
+	qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_CLEAR_ALL,
+			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
+	qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
+			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
+	qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
+}
+
+static void
 test_ipc_bulk_events(void)
 {
 	int32_t c = 0;
@@ -1070,18 +1148,28 @@ START_TEST(test_ipc_stress_test_us)
 	qb_enter();
 	send_event_on_created = QB_FALSE;
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_stress_test();
 	qb_leave();
 }
 END_TEST
 
+START_TEST(test_ipc_stress_connections_us)
+{
+	qb_enter();
+	ipc_type = QB_IPC_SOCKET;
+	set_ipc_name(__func__);
+	test_ipc_stress_connections();
+	qb_leave();
+}
+END_TEST
+
 START_TEST(test_ipc_bulk_events_us)
 {
 	qb_enter();
 	send_event_on_created = QB_FALSE;
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_bulk_events();
 	qb_leave();
 }
@@ -1137,7 +1225,7 @@ START_TEST(test_ipc_event_on_created_us)
 	qb_enter();
 	send_event_on_created = QB_TRUE;
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_event_on_created();
 	qb_leave();
 }
@@ -1199,7 +1287,7 @@ START_TEST(test_ipc_disconnect_after_created_us)
 	qb_enter();
 	disconnect_after_created = QB_TRUE;
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_disconnect_after_created();
 	qb_leave();
 }
@@ -1238,7 +1326,7 @@ START_TEST(test_ipc_server_fail_soc)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_server_fail();
 	qb_leave();
 }
@@ -1248,7 +1336,7 @@ START_TEST(test_ipc_disp_shm)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_dispatch();
 	qb_leave();
 }
@@ -1259,17 +1347,27 @@ START_TEST(test_ipc_stress_test_shm)
 	qb_enter();
 	send_event_on_created = QB_FALSE;
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_stress_test();
 	qb_leave();
 }
 END_TEST
 
+START_TEST(test_ipc_stress_connections_shm)
+{
+	qb_enter();
+	ipc_type = QB_IPC_SHM;
+	set_ipc_name(__func__);
+	test_ipc_stress_connections();
+	qb_leave();
+}
+END_TEST
+
 START_TEST(test_ipc_bulk_events_shm)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_bulk_events();
 	qb_leave();
 }
@@ -1280,7 +1378,7 @@ START_TEST(test_ipc_event_on_created_shm)
 	qb_enter();
 	send_event_on_created = QB_TRUE;
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_event_on_created();
 	qb_leave();
 }
@@ -1290,7 +1388,7 @@ START_TEST(test_ipc_server_fail_shm)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_server_fail();
 	qb_leave();
 }
@@ -1331,7 +1429,7 @@ START_TEST(test_ipc_service_ref_count_shm)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SHM;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_service_ref_count();
 	qb_leave();
 }
@@ -1341,7 +1439,7 @@ START_TEST(test_ipc_service_ref_count_us)
 {
 	qb_enter();
 	ipc_type = QB_IPC_SOCKET;
-	ipc_name = __func__;
+	set_ipc_name(__func__);
 	test_ipc_service_ref_count();
 	qb_leave();
 }
@@ -1439,6 +1537,11 @@ make_shm_suite(void)
 	tcase_set_timeout(tc, 10);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("ipc_stress_connections_shm");
+	tcase_add_test(tc, test_ipc_stress_connections_shm);
+	tcase_set_timeout(tc, 200);
+	suite_add_tcase(s, tc);
+
 	return s;
 }
 
@@ -1513,6 +1616,11 @@ make_soc_suite(void)
 	tcase_set_timeout(tc, 10);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("ipc_stress_connections_us");
+	tcase_add_test(tc, test_ipc_stress_connections_us);
+	tcase_set_timeout(tc, 200);
+	suite_add_tcase(s, tc);
+
 	return s;
 }
 
@@ -1524,6 +1632,7 @@ main(void)
 	Suite *s;
 	int32_t do_shm_tests = QB_TRUE;
 
+	set_ipc_name("ipc_test");
 #ifdef DISABLE_IPC_SHM
 	do_shm_tests = QB_FALSE;
 #endif /* DISABLE_IPC_SHM */
diff --git a/tests/check_log.c b/tests/check_log.c
index 22eb0a5..56c9305 100644
--- a/tests/check_log.c
+++ b/tests/check_log.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Red Hat, Inc.
+ * Copyright (c) 2011-2015 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -708,6 +708,63 @@ START_TEST(test_threaded_logging)
 }
 END_TEST
 
+START_TEST(test_extended_information)
+{
+	int32_t t;
+	int32_t rc;
+	int extended;
+
+	qb_log_init("test", LOG_USER, LOG_DEBUG);
+	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
+
+	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
+	_ck_assert_int(t, >, QB_LOG_STDOUT);
+	qb_log_format_set(t, "%b");
+	rc = qb_log_filter_fn_set(NULL);
+	ck_assert_int_eq(rc, 0);
+	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL, QB_LOG_FILTER_FILE,
+			       "*", LOG_TRACE);
+	ck_assert_int_eq(rc, 0);
+	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL, QB_LOG_FILTER_FORMAT,
+			       "*", LOG_TRACE);
+	ck_assert_int_eq(rc, 0);
+	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FORMAT,
+			       "*", LOG_TRACE);
+	ck_assert_int_eq(rc, 0);
+	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
+	ck_assert_int_eq(rc, 0);
+
+	for (extended = QB_FALSE; extended <= QB_TRUE; ++extended) {
+		rc = qb_log_ctl(t, QB_LOG_CONF_EXTENDED, extended);
+		ck_assert_int_eq(rc, 0);
+
+		num_msgs = 0;
+
+		memset(test_buf, 0, sizeof(test_buf));
+		qb_log(LOG_ERR, "message with no extended information");
+		ck_assert_str_eq(test_buf, "message with no extended information");
+
+		memset(test_buf, 0, sizeof(test_buf));
+		qb_log(LOG_ERR, "message with empty extended information "QB_XS);
+		ck_assert_str_eq(test_buf, "message with empty extended information ");
+
+		memset(test_buf, 0, sizeof(test_buf));
+		qb_log(LOG_ERR, QB_XS" message with only extended information");
+		ck_assert_str_eq(test_buf, extended?
+				 "| message with only extended information" : "");
+
+		memset(test_buf, 0, sizeof(test_buf));
+		qb_log(LOG_ERR, "message with extended information "QB_XS" (namely this)");
+		ck_assert_str_eq(test_buf, extended?
+				 "message with extended information | (namely this)"
+				 : "message with extended information ");
+
+		ck_assert_int_eq(num_msgs, (extended? 4 : 3));
+	}
+	qb_log_fini();
+}
+END_TEST
+
 static Suite *
 log_suite(void)
 {
@@ -751,6 +808,10 @@ log_suite(void)
 	tcase_add_test(tc, test_threaded_logging);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("extended_information");
+	tcase_add_test(tc, test_extended_information);
+	suite_add_tcase(s, tc);
+
 	return s;
 }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-ha/libqb.git



More information about the Debian-HA-Commits mailing list