From 3345de3561e8bb197a6cc9a05c0570a319461f11 Mon Sep 17 00:00:00 2001 From: Angus Salkeld Date: Tue, 7 Feb 2012 22:27:05 +1100 Subject: [PATCH] Rebase to v0.10.0 (bug fix release) Signed-off-by: Angus Salkeld --- .gitignore | 1 + 0000-test-with-output.patch | 44 ------ 0001-LOOP-fix-the-todo-calculations.patch | 98 -------------- ...-for-a-single-job-causing-a-cpu-spin.patch | 127 ------------------ ...ent-jobs-from-consuming-too-much-cpu.patch | 58 -------- libqb.spec | 27 ++-- sources | 2 +- 7 files changed, 21 insertions(+), 336 deletions(-) delete mode 100644 0001-LOOP-fix-the-todo-calculations.patch delete mode 100644 0002-TEST-check-for-a-single-job-causing-a-cpu-spin.patch delete mode 100644 0003-LOOP-prevent-jobs-from-consuming-too-much-cpu.patch diff --git a/.gitignore b/.gitignore index 672538e..8861a4b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /libqb-0.7.0.tar.gz /libqb-0.8.1.tar.xz /libqb-0.9.0.tar.xz +/libqb-0.10.0.tar.xz diff --git a/0000-test-with-output.patch b/0000-test-with-output.patch index 40d0c61..d678982 100644 --- a/0000-test-with-output.patch +++ b/0000-test-with-output.patch @@ -22,48 +22,4 @@ index fd158aa..e2efcc8 100644 dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from dnl normal compilation. When a failure occurs, it will then display the full dnl command line -diff --git a/tests/Makefile.am b/tests/Makefile.am -index b1108d9..32f2bd4 100644 ---- a/tests/Makefile.am -+++ b/tests/Makefile.am -@@ -89,11 +89,13 @@ bench_log_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la - if HAVE_CHECK - EXTRA_DIST += resources.test - --TESTS = array.test map.test rb.test log.test loop.test ipc.test resources.test -+TESTS = array.test map.test rb.test log.test resources.test -+# loop.test ipc.test - --resources.log: rb.log log.log ipc.log -+resources.log: rb.log log.log - --check_PROGRAMS = array.test map.test rb.test log.test loop.test ipc.test -+check_PROGRAMS = array.test map.test rb.test log.test -+# loop.test ipc.test - check_SCRIPTS = resources.test - - array_test_SOURCES = check_array.c $(top_builddir)/include/qb/qbarray.h -@@ -108,13 +110,13 @@ rb_test_SOURCES = check_rb.c $(top_builddir)/include/qb/qbrb.h - rb_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include - rb_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@ - --loop_test_SOURCES = check_loop.c $(top_builddir)/include/qb/qbloop.h --loop_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include --loop_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@ -- --ipc_test_SOURCES = check_ipc.c $(top_builddir)/include/qb/qbipcc.h $(top_builddir)/include/qb/qbipcs.h --ipc_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include --ipc_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@ -+#loop_test_SOURCES = check_loop.c $(top_builddir)/include/qb/qbloop.h -+#loop_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include -+#loop_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@ -+# -+#ipc_test_SOURCES = check_ipc.c $(top_builddir)/include/qb/qbipcc.h $(top_builddir)/include/qb/qbipcs.h -+#ipc_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include -+#ipc_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@ - - log_test_SOURCES = check_log.c $(top_builddir)/include/qb/qblog.h - log_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include --- -1.7.7.6 diff --git a/0001-LOOP-fix-the-todo-calculations.patch b/0001-LOOP-fix-the-todo-calculations.patch deleted file mode 100644 index 140cbc0..0000000 --- a/0001-LOOP-fix-the-todo-calculations.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 1f269e7bfc916f2ae852e8a7faa591af74c59f05 Mon Sep 17 00:00:00 2001 -From: Angus Salkeld -Date: Mon, 6 Feb 2012 22:31:55 +1100 -Subject: [PATCH 1/3] LOOP: fix the todo calculations. - -Signed-off-by: Angus Salkeld ---- - lib/loop.c | 22 ++++++++++++---------- - lib/loop_job.c | 5 ++++- - 2 files changed, 16 insertions(+), 11 deletions(-) - -diff --git a/lib/loop.c b/lib/loop.c -index 142e7eb..45ceb3f 100644 ---- a/lib/loop.c -+++ b/lib/loop.c -@@ -26,7 +26,7 @@ - #include "loop_int.h" - #include "util_int.h" - --static int32_t -+static void - qb_loop_run_level(struct qb_loop_level *level) - { - struct qb_loop_item *job; -@@ -44,13 +44,12 @@ Ill_have_another: - level->todo--; - processed++; - if (level->l->stop_requested) { -- return processed; -+ return; - } - if (processed < level->to_process) { - goto Ill_have_another; - } - } -- return processed; - } - - void -@@ -139,20 +138,23 @@ qb_loop_run(struct qb_loop *l) - if (todo > 0) { - ms_timeout = 0; - } else { -- todo = 0; - if (l->timer_source) { - ms_timeout = qb_loop_timer_msec_duration_to_expire(l->timer_source); - } else { - ms_timeout = -1; - } - } -- todo += l->fd_source->poll(l->fd_source, ms_timeout); -- -- for (p = QB_LOOP_HIGH; p >= p_stop; p--) { -- todo -= qb_loop_run_level(&l->level[p]); -- if (l->stop_requested) { -- return; -+ (void)l->fd_source->poll(l->fd_source, ms_timeout); -+ -+ todo = 0; -+ for (p = QB_LOOP_HIGH; p >= QB_LOOP_LOW; p--) { -+ if (p >= p_stop) { -+ qb_loop_run_level(&l->level[p]); -+ if (l->stop_requested) { -+ return; -+ } - } -+ todo += l->level[p].todo; - } - } while (!l->stop_requested); - } -diff --git a/lib/loop_job.c b/lib/loop_job.c -index c17663d..123d1af 100644 ---- a/lib/loop_job.c -+++ b/lib/loop_job.c -@@ -48,16 +48,19 @@ get_more_jobs(struct qb_loop_source *s, int32_t ms_timeout) - { - int32_t p; - int32_t new_jobs = 0; -+ int32_t level_jobs = 0; - - /* - * this is simple, move jobs from wait_head to job_head - */ - for (p = QB_LOOP_LOW; p <= QB_LOOP_HIGH; p++) { - if (!qb_list_empty(&s->l->level[p].wait_head)) { -- new_jobs += qb_list_length(&s->l->level[p].wait_head); -+ level_jobs = qb_list_length(&s->l->level[p].wait_head); -+ new_jobs += level_jobs; - qb_list_splice(&s->l->level[p].wait_head, - &s->l->level[p].job_head); - qb_list_init(&s->l->level[p].wait_head); -+ s->l->level[p].todo += level_jobs; - } - } - return new_jobs; --- -1.7.7.6 - diff --git a/0002-TEST-check-for-a-single-job-causing-a-cpu-spin.patch b/0002-TEST-check-for-a-single-job-causing-a-cpu-spin.patch deleted file mode 100644 index 28c7092..0000000 --- a/0002-TEST-check-for-a-single-job-causing-a-cpu-spin.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 7d2739fdd23e118bbaa42b3c43381b88ea842c88 Mon Sep 17 00:00:00 2001 -From: Angus Salkeld -Date: Sat, 4 Feb 2012 12:28:45 +1100 -Subject: [PATCH 2/3] TEST: check for a single job causing a cpu spin - -Signed-off-by: Angus Salkeld ---- - tests/check_loop.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 files changed, 61 insertions(+), 2 deletions(-) - -diff --git a/tests/check_loop.c b/tests/check_loop.c -index 50e80da..eb79a51 100644 ---- a/tests/check_loop.c -+++ b/tests/check_loop.c -@@ -60,6 +60,7 @@ static void job_1_r(void *data) - res = qb_loop_job_add(l, QB_LOOP_MED, data, job_2); - ck_assert_int_eq(res, 0); - } -+ - static void job_1_add_nuts(void *data) - { - int32_t res; -@@ -153,7 +154,6 @@ START_TEST(test_loop_job_4) - } - END_TEST - -- - START_TEST(test_loop_job_nuts) - { - int32_t res; -@@ -169,6 +169,53 @@ START_TEST(test_loop_job_nuts) - } - END_TEST - -+static qb_util_stopwatch_t *rl_sw; -+#define RATE_LIMIT_RUNTIME_SEC 3 -+ -+static void job_add_self(void *data) -+{ -+ int32_t res; -+ uint64_t elapsed1; -+ qb_loop_t *l = (qb_loop_t *)data; -+ -+ job_1_run_count++; -+ qb_util_stopwatch_stop(rl_sw); -+ elapsed1 = qb_util_stopwatch_us_elapsed_get(rl_sw); -+ if (elapsed1 > (RATE_LIMIT_RUNTIME_SEC * QB_TIME_US_IN_SEC)) { -+ /* run for 3 seconds */ -+ qb_loop_stop(l); -+ return; -+ } -+ res = qb_loop_job_add(l, QB_LOOP_MED, data, job_add_self); -+ ck_assert_int_eq(res, 0); -+} -+ -+START_TEST(test_job_rate_limit) -+{ -+ int32_t res; -+ qb_loop_t *l = qb_loop_create(); -+ fail_if(l == NULL); -+ -+ rl_sw = qb_util_stopwatch_create(); -+ fail_if(rl_sw == NULL); -+ -+ qb_util_stopwatch_start(rl_sw); -+ -+ res = qb_loop_job_add(l, QB_LOOP_MED, l, job_add_self); -+ ck_assert_int_eq(res, 0); -+ -+ qb_loop_run(l); -+ /* -+ * the test is to confirm that a single job does not run away -+ * and cause cpu spin. We are going to say that a spin is more than -+ * one job per 50ms if there is only one job pending in the loop. -+ */ -+ _ck_assert_int(job_1_run_count, <, (RATE_LIMIT_RUNTIME_SEC * (QB_TIME_MS_IN_SEC/50)) + 1); -+ qb_loop_destroy(l); -+ qb_util_stopwatch_free(rl_sw); -+} -+END_TEST -+ - static Suite *loop_job_suite(void) - { - TCase *tc; -@@ -188,6 +235,12 @@ static Suite *loop_job_suite(void) - - tc = tcase_create("run_500"); - tcase_add_test(tc, test_loop_job_nuts); -+ tcase_set_timeout(tc, 5); -+ suite_add_tcase(s, tc); -+ -+ tc = tcase_create("rate_limit"); -+ tcase_add_test(tc, test_job_rate_limit); -+ tcase_set_timeout(tc, 5); - suite_add_tcase(s, tc); - - return s; -@@ -465,12 +518,17 @@ static Suite *loop_timer_suite(void) - tcase_add_test(tc, test_loop_timer_expire_leak); - tcase_set_timeout(tc, 30); - suite_add_tcase(s, tc); -+ return s; -+} - -+static Suite *loop_signal_suite(void) -+{ -+ TCase *tc; -+ Suite *s = suite_create("loop_signal_suite"); - tc = tcase_create("signals"); - tcase_add_test(tc, test_loop_sig_handling); - tcase_set_timeout(tc, 10); - suite_add_tcase(s, tc); -- - return s; - } - -@@ -479,6 +537,7 @@ int32_t main(void) - int32_t number_failed; - SRunner *sr = srunner_create(loop_job_suite()); - srunner_add_suite (sr, loop_timer_suite()); -+ srunner_add_suite (sr, loop_signal_suite()); - - qb_log_init("check", LOG_USER, LOG_EMERG); - qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE); --- -1.7.7.6 - diff --git a/0003-LOOP-prevent-jobs-from-consuming-too-much-cpu.patch b/0003-LOOP-prevent-jobs-from-consuming-too-much-cpu.patch deleted file mode 100644 index b1fa851..0000000 --- a/0003-LOOP-prevent-jobs-from-consuming-too-much-cpu.patch +++ /dev/null @@ -1,58 +0,0 @@ -From cf198dc03e51439da9e824abb7acc29c30e691ae Mon Sep 17 00:00:00 2001 -From: Angus Salkeld -Date: Mon, 6 Feb 2012 22:35:30 +1100 -Subject: [PATCH 3/3] LOOP: prevent jobs from consuming too much cpu. - -Signed-off-by: Angus Salkeld ---- - lib/loop.c | 23 ++++++++++++++++++++--- - 1 files changed, 20 insertions(+), 3 deletions(-) - -diff --git a/lib/loop.c b/lib/loop.c -index 45ceb3f..3e10b89 100644 ---- a/lib/loop.c -+++ b/lib/loop.c -@@ -118,6 +118,8 @@ qb_loop_run(struct qb_loop *l) - int32_t p; - int32_t p_stop = QB_LOOP_LOW; - int32_t todo = 0; -+ int32_t job_todo; -+ int32_t timer_todo; - int32_t ms_timeout; - - l->stop_requested = QB_FALSE; -@@ -130,13 +132,28 @@ qb_loop_run(struct qb_loop *l) - } - - if (l->job_source && l->job_source->poll) { -- todo += l->job_source->poll(l->job_source, 0); -+ job_todo = l->job_source->poll(l->job_source, 0); -+ } else { -+ job_todo = 0; - } - if (l->timer_source && l->timer_source->poll) { -- todo += l->timer_source->poll(l->timer_source, 0); -+ timer_todo = l->timer_source->poll(l->timer_source, 0); -+ } else { -+ timer_todo = 0; - } -- if (todo > 0) { -+ if (todo > 0 || timer_todo > 0) { -+ /* -+ * if there are old todos or timer todos then don't wait. -+ */ - ms_timeout = 0; -+ } else if (job_todo > 0) { -+ todo = 0; -+ /* -+ * if we only have jobs to do (not timers or old todos) -+ * then set a non-zero timeout. Jobs can spin out of -+ * control if someone keeps adding them. -+ */ -+ ms_timeout = 50; - } else { - if (l->timer_source) { - ms_timeout = qb_loop_timer_msec_duration_to_expire(l->timer_source); --- -1.7.7.6 - diff --git a/libqb.spec b/libqb.spec index 4328c49..d13c740 100644 --- a/libqb.spec +++ b/libqb.spec @@ -1,6 +1,6 @@ Name: libqb -Version: 0.9.0 -Release: 2%{?dist} +Version: 0.10.0 +Release: 1%{?dist} Summary: An IPC library for high performance servers Group: System Environment/Libraries @@ -10,9 +10,6 @@ Source0: https://fedorahosted.org/releases/q/u/quarterback/%{name}-%{vers BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Patch1: 0000-test-with-output.patch -Patch2: 0001-LOOP-fix-the-todo-calculations.patch -Patch3: 0002-TEST-check-for-a-single-job-causing-a-cpu-spin.patch -Patch4: 0003-LOOP-prevent-jobs-from-consuming-too-much-cpu.patch BuildRequires: libtool doxygen procps check-devel automake @@ -26,9 +23,6 @@ Initially these are IPC and poll. %setup -q %patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 %build ./autogen.sh @@ -74,6 +68,23 @@ developing applications that use %{name}. %{_mandir}/man3/qb*3* %changelog +* Tue Feb 07 2012 Angus Salkeld - 0.10.0-1 +- LOOP: handle errors from the poll function +- LOOP: make the item type applicable to jobs too. +- LOOP: fix the todo calculations. +- TEST: check for a single job causing a cpu spin +- LOOP: prevent jobs from consuming too much cpu. +- Get coverity to ignore this warning. +- Change example code to use fgets instead of gets +- LOG: pass the result of qb_log_thread_start() back to the user +- Fix some issues found by clang +- Add clang-analyzer check +- Add a split timer to the stopwatch. +- IPC: merge common code into new function +- IPC: better handle a disconnect been called from within connection_created() +- IPC: fix scary typo +- IPC: fix server error handling + * Mon Feb 06 2012 Angus Salkeld - 0.9.0-2 - Fix a spin in the mainloop when a timer or poll gets removed When in the job queue (#787196). diff --git a/sources b/sources index 8100772..d982265 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -104563dd7c3ae52451663a8539ba1ca3 libqb-0.9.0.tar.xz +4a5082a17c4dfa2ccf50dcc39d132ebc libqb-0.10.0.tar.xz