From 9cf788cc397fb37e5bd0e1681aa139e2682cc3c1 Mon Sep 17 00:00:00 2001 From: Jung-Sang Ahn Date: Thu, 26 Sep 2019 22:37:17 -0700 Subject: [PATCH] Fix to crash in response meta callback * If response meta callback function returns `false`, it will cause null pointer access. * Added random denial test. --- src/asio_service.cxx | 2 +- tests/unit/asio_service_test.cxx | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/asio_service.cxx b/src/asio_service.cxx index e13b54d0..390225b2 100644 --- a/src/asio_service.cxx +++ b/src/asio_service.cxx @@ -1298,7 +1298,7 @@ class asio_rpc_client ( cs_new ( sstrfmt( "response meta verification failed: " "from peer %d, %s:%s") - .fmt( rsp->get_dst(), host_.c_str(), + .fmt( req->get_dst(), host_.c_str(), port_.c_str() ), req ) ); close_socket(); diff --git a/tests/unit/asio_service_test.cxx b/tests/unit/asio_service_test.cxx index 483a486e..cb44fee3 100644 --- a/tests/unit/asio_service_test.cxx +++ b/tests/unit/asio_service_test.cxx @@ -388,6 +388,85 @@ int message_meta_test() { return 0; } +bool test_read_meta_random_denial( std::atomic* start_denial, + const asio_service::meta_cb_params& params, + const std::string& meta ) +{ + if (!start_denial) return true; + + int r = std::rand(); + if (r % 25 == 0) return false; + return true; +} + +int message_meta_random_denial_test() { + reset_log_files(); + + std::string s1_addr = "127.0.0.1:20010"; + std::string s2_addr = "127.0.0.1:20020"; + std::string s3_addr = "127.0.0.1:20030"; + + RaftAsioPkg s1(1, s1_addr); + RaftAsioPkg s2(2, s2_addr); + RaftAsioPkg s3(3, s3_addr); + std::vector pkgs = {&s1, &s2, &s3}; + + std::atomic read_req_cb_count(0); + std::atomic write_req_cb_count(0); + std::atomic write_resp_cb_count(0); + std::atomic start_denial(false); + + _msg("launching asio-raft servers with meta callback\n"); + for (RaftAsioPkg* rr: pkgs) { + rr->setMetaCallback + ( std::bind( test_read_meta_random_denial, + &start_denial, + std::placeholders::_1, + std::placeholders::_2 ), + std::bind( test_write_req_meta, + &write_req_cb_count, + std::placeholders::_1 ), + std::bind( test_read_meta_random_denial, + &start_denial, + std::placeholders::_1, + std::placeholders::_2 ), + std::bind( test_write_resp_meta, + &write_resp_cb_count, + std::placeholders::_1 ), + true ); + } + CHK_Z( launch_servers(pkgs, false) ); + + _msg("organizing raft group\n"); + CHK_Z( make_group(pkgs) ); + + CHK_TRUE( s1.raftServer->is_leader() ); + CHK_EQ(1, s1.raftServer->get_leader()); + CHK_EQ(1, s2.raftServer->get_leader()); + CHK_EQ(1, s3.raftServer->get_leader()); + + TestSuite::sleep_sec(1, "wait for Raft group ready"); + start_denial = true; + + for (size_t ii=0; ii<100; ++ii) { + std::string msg_str = std::to_string(ii); + ptr msg = buffer::alloc(sizeof(uint32_t) + msg_str.size()); + buffer_serializer bs(msg); + bs.put_str(msg_str); + s1.raftServer->append_entries( {msg} ); + } + + TestSuite::sleep_sec(5, "wait for random denial"); + + s1.raftServer->shutdown(); + s2.raftServer->shutdown(); + s3.raftServer->shutdown(); + TestSuite::sleep_sec(1, "shutting down"); + + SimpleLogger::shutdown(); + return 0; +} + std::string test_write_empty_meta( std::atomic* count, const asio_service::meta_cb_params& params ) @@ -699,6 +778,9 @@ int main(int argc, char** argv) { empty_meta_test, TestRange( {false, true} ) ); + ts.doTest( "message meta random denial test", + message_meta_random_denial_test ); + ts.doTest( "response hint test", response_hint_test, TestRange( {false, true} ) );