From 580f51c22e2443bf5abe30f8d7e770fc30511a92 Mon Sep 17 00:00:00 2001 From: bert hubert Date: Tue, 10 Oct 2017 12:48:55 +0200 Subject: [PATCH 1/4] Fix crash on older boost when receiving an exception from an MThread for older boost fcontext versions, we would return a boolean that said 'we caught an exception for you and stored it in ctx', but we would not actually retrieve the origin ctx, and then blindly attempt to rethrow the exception (not) stored in the ctx we did have, leading to a crash. We now send back the actual ctx, and check it for a stored exception. --- pdns/mtasker_fcontext.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pdns/mtasker_fcontext.cc b/pdns/mtasker_fcontext.cc index 362a2f797fc5..0ab87b6f6cc3 100644 --- a/pdns/mtasker_fcontext.cc +++ b/pdns/mtasker_fcontext.cc @@ -152,7 +152,7 @@ threadWrapper (transfer_t const t) { #if BOOST_VERSION < 106100 jump_fcontext (reinterpret_cast(&ctx->uc_mcontext), static_cast(next_ctx), - static_cast(ctx->exception)); + reinterpret_cast(ctx)); #else jump_fcontext (static_cast(next_ctx), 0); #endif @@ -189,10 +189,12 @@ pdns_swapcontext or we switch back to pdns_swapcontext(), in both case we will be returning from a call to jump_fcontext(). */ #if BOOST_VERSION < 106100 - if (jump_fcontext (reinterpret_cast(&octx.uc_mcontext), - static_cast(ctx.uc_mcontext), 0)) { - std::rethrow_exception (ctx.exception); - } + intptr_t ptr = jump_fcontext(reinterpret_cast(&octx.uc_mcontext), + static_cast(ctx.uc_mcontext), 0); + + auto origctx = reinterpret_cast(ptr); + if(origctx && origctx->exception) + std::rethrow_exception (origctx->exception); #else transfer_t res = jump_fcontext (static_cast(ctx.uc_mcontext), &octx.uc_mcontext); if (res.data) { From 887316ee6c103850789ed9f3cfcf462b0dce73d8 Mon Sep 17 00:00:00 2001 From: bert hubert Date: Tue, 10 Oct 2017 14:41:01 +0200 Subject: [PATCH 2/4] if there was an mtasker waiter with no associated timeout, we would loop forever in MTasker::schedule() --- pdns/mtasker.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pdns/mtasker.cc b/pdns/mtasker.cc index 43294c9537cc..9fcb7d31f2dd 100644 --- a/pdns/mtasker.cc +++ b/pdns/mtasker.cc @@ -344,6 +344,8 @@ templatebool MTasker::schedule(struct timeval* n } else if(i->ttd.tv_sec) break; + else + ++i; } } return false; From 7346028e546b552c4534eb49e8320914142a3488 Mon Sep 17 00:00:00 2001 From: bert hubert Date: Tue, 10 Oct 2017 14:41:44 +0200 Subject: [PATCH 3/4] add two tests for MTasker, including catching an exception --- pdns/recursordist/Makefile.am | 4 +++ pdns/recursordist/test-mtasker.cc | 60 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 pdns/recursordist/test-mtasker.cc diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index 0775481e1296..082c90c2785b 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -206,6 +206,7 @@ testrunner_SOURCES = \ ixfr.cc ixfr.hh \ logger.cc logger.hh \ misc.cc misc.hh \ + mtasker_fcontext.cc \ negcache.hh negcache.cc \ namespaces.hh \ nsecrecords.cc \ @@ -237,6 +238,7 @@ testrunner_SOURCES = \ test-iputils_hh.cc \ test-ixfr_cc.cc \ test-misc_hh.cc \ + test-mtasker.cc \ test-nmtree.cc \ test-negcache_cc.cc \ test-rcpgenerator_cc.cc \ @@ -254,10 +256,12 @@ testrunner_SOURCES = \ testrunner_LDFLAGS = \ $(AM_LDFLAGS) \ + $(BOOST_CONTEXT_LDFLAGS) \ $(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS) \ $(LIBCRYPTO_LDFLAGS) testrunner_LDADD = \ + $(BOOST_CONTEXT_LIBS) \ $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \ $(LIBCRYPTO_LIBS) \ $(RT_LIBS) diff --git a/pdns/recursordist/test-mtasker.cc b/pdns/recursordist/test-mtasker.cc new file mode 100644 index 000000000000..9da5825586c1 --- /dev/null +++ b/pdns/recursordist/test-mtasker.cc @@ -0,0 +1,60 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "mtasker.hh" + +BOOST_AUTO_TEST_SUITE(mtasker_cc) + +static int g_result; + +static void doSomething(void* p) +{ + MTasker<>* mt = reinterpret_cast*>(p); + int i=12, o; + mt->waitEvent(i, &o); + g_result = o; + +} + +BOOST_AUTO_TEST_CASE(test_Simple) { + MTasker<> mt; + mt.makeThread(doSomething, &mt); + struct timeval now; + gettimeofday(&now, 0); + bool first=true; + int o=24; + for(;;) { + while(mt.schedule(&now)); + if(first) { + mt.sendEvent(12, &o); + first=false; + } + if(mt.noProcesses()) + break; + } + BOOST_CHECK_EQUAL(g_result, o); +} + +static void willThrow(void* p) +{ + throw std::runtime_error("Help!"); +} + + +BOOST_AUTO_TEST_CASE(test_MtaskerException) { + BOOST_CHECK_EXCEPTION( { + MTasker<> mt; + mt.makeThread(willThrow, 0); + struct timeval now; + + for(;;) { + mt.schedule(&now); + } + }, std::exception, [](const std::exception& e) { return true; }); +} +BOOST_AUTO_TEST_SUITE_END() From 2eca39afdf5cb26bfbaa9f2091a44456551041ee Mon Sep 17 00:00:00 2001 From: bert hubert Date: Tue, 10 Oct 2017 16:06:51 +0200 Subject: [PATCH 4/4] use BOOST_CHECK_THROW, link in boost_context.cc --- pdns/recursordist/Makefile.am | 2 +- pdns/recursordist/test-mtasker.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index 082c90c2785b..a3ab6121fd39 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -206,7 +206,7 @@ testrunner_SOURCES = \ ixfr.cc ixfr.hh \ logger.cc logger.hh \ misc.cc misc.hh \ - mtasker_fcontext.cc \ + mtasker_context.cc \ negcache.hh negcache.cc \ namespaces.hh \ nsecrecords.cc \ diff --git a/pdns/recursordist/test-mtasker.cc b/pdns/recursordist/test-mtasker.cc index 9da5825586c1..f6f1b5b46549 100644 --- a/pdns/recursordist/test-mtasker.cc +++ b/pdns/recursordist/test-mtasker.cc @@ -47,7 +47,7 @@ static void willThrow(void* p) BOOST_AUTO_TEST_CASE(test_MtaskerException) { - BOOST_CHECK_EXCEPTION( { + BOOST_CHECK_THROW( { MTasker<> mt; mt.makeThread(willThrow, 0); struct timeval now; @@ -55,6 +55,6 @@ BOOST_AUTO_TEST_CASE(test_MtaskerException) { for(;;) { mt.schedule(&now); } - }, std::exception, [](const std::exception& e) { return true; }); + }, std::exception); } BOOST_AUTO_TEST_SUITE_END()