[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.
[](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