You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2019/04/11 17:07:20 UTC
[qpid-proton] 14/15: PROTON-2027: Test case with two closing
connection contexts competing with a third context in
pn_proactor_disconnect().
This is an automated email from the ASF dual-hosted git repository.
robbie pushed a commit to branch 0.27.x
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git
commit 8a84224cc79377b09bed59a33d1d11b641b45505
Author: Cliff Jansen <cl...@apache.org>
AuthorDate: Mon Apr 8 04:58:48 2019 -0700
PROTON-2027: Test case with two closing connection contexts competing with a third context in pn_proactor_disconnect().
(cherry picked from commit f973528912b3b74e8d1e50317429e202e9f51ec4)
---
cpp/src/container_test.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/cpp/src/container_test.cpp b/cpp/src/container_test.cpp
index 0e74aaa..5ad0e57 100644
--- a/cpp/src/container_test.cpp
+++ b/cpp/src/container_test.cpp
@@ -375,7 +375,7 @@ void test_container_mt_stop_empty() {
} catch (const std::exception &e) {
std::cerr << FAIL_MSG(e.what()) << std::endl;
// If join hangs, let the test die by timeout. We cannot
- // detach and continue: deleting the container while t is
+ // detach and continue: deleting the container while it is
// still alive will put the process in an undefined state.
t.join();
throw;
@@ -406,6 +406,64 @@ void test_container_mt_stop() {
}
}
+class test_mt_handler_wq : public test_mt_handler {
+public:
+ proton::work_queue *wq_;
+ proton::connection connection_;
+ std::mutex wqlock_;
+
+ test_mt_handler_wq() : wq_(0) {}
+
+ void on_connection_open(proton::connection &c) PN_CPP_OVERRIDE {
+ {
+ std::unique_lock<std::mutex> l(wqlock_);
+ // Just record first connection side, inbound or outbound
+ if (!connection_) {
+ connection_ = c;
+ wq_ = &c.work_queue();
+ }
+ else
+ return;
+ }
+ test_mt_handler::on_connection_open(c);
+ }
+ void initiate_close() {
+ std::unique_lock<std::mutex> l(wqlock_);
+ wq_->add( [this]() { this->do_close(); });
+ }
+ void do_close() { connection_.close(); }
+ void on_connection_close(proton::connection &) PN_CPP_OVERRIDE { set("closed"); }
+};
+
+void test_container_mt_close_race() {
+ test_mt_handler_wq th;
+ proton::container c(th);
+ c.auto_stop(false);
+ container_runner runner(c);
+ auto t = std::thread(runner);
+ // Must ensure that thread is joined
+ try {
+ test_listen_handler lh;
+ ASSERT_EQUAL("start", th.wait());
+ c.listen("//:0", lh); // Also opens a connection
+ ASSERT_EQUAL("open", th.wait());
+ th.initiate_close();
+ ASSERT_EQUAL("closed", th.wait());
+ // The two sides of the connection are closing, each with its
+ // own connection context. Start a proactor disconnect to run
+ // competing close cleanup in a third context. PROTON-2027.
+ c.stop();
+ t.join();
+ } catch (const std::exception& e) {
+ std::cerr << FAIL_MSG(e.what()) << std::endl;
+ // If join hangs, let the test die by timeout. We cannot
+ // detach and continue: deleting the container while t is
+ // still alive will put the process in an undefined state.
+ t.join();
+ throw;
+ }
+}
+
#endif
} // namespace
@@ -426,6 +484,7 @@ int main(int argc, char** argv) {
#if PN_CPP_SUPPORTS_THREADS
RUN_ARGV_TEST(failed, test_container_mt_stop_empty());
RUN_ARGV_TEST(failed, test_container_mt_stop());
+ RUN_ARGV_TEST(failed, test_container_mt_close_race());
#endif
return failed;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org