PROTON-1734: Fix the semantics of pn_proactor_disconnect() - Make sure that an PN_PROACTOR_INACTIVE event is always generated even if the proactor was inactive before. This ensures that we can use disconnect effectively even before making connections
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/5d47e615 Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/5d47e615 Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/5d47e615 Branch: refs/heads/master Commit: 5d47e615a8ba322a65fd41735c0c6adb36828bed Parents: 093355f Author: Andrew Stitcher <astitc...@apache.org> Authored: Thu Feb 22 01:58:55 2018 -0500 Committer: Andrew Stitcher <astitc...@apache.org> Committed: Thu Feb 22 10:40:15 2018 -0500 ---------------------------------------------------------------------- proton-c/bindings/cpp/src/proactor_container_impl.cpp | 14 +++++++++++++- proton-c/bindings/cpp/src/proactor_container_impl.hpp | 1 + proton-c/src/proactor/epoll.c | 8 ++++++-- proton-c/src/proactor/libuv.c | 10 +++++++--- 4 files changed, 27 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5d47e615/proton-c/bindings/cpp/src/proactor_container_impl.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp index 988521c..15eff0a 100644 --- a/proton-c/bindings/cpp/src/proactor_container_impl.cpp +++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp @@ -143,7 +143,7 @@ class work_queue::impl* container::impl::make_work_queue(container& c) { container::impl::impl(container& c, const std::string& id, messaging_handler* mh) : threads_(0), container_(c), proactor_(pn_proactor()), handler_(mh), id_(id), - auto_stop_(true), stopping_(false) + reconnecting_(0), auto_stop_(true), stopping_(false) {} container::impl::~impl() { @@ -217,6 +217,15 @@ void container::impl::start_connection(const url& url, pn_connection_t *pnc) { } void container::impl::reconnect(pn_connection_t* pnc) { + --reconnecting_; + + if (stopping_ && reconnecting_==0) { + pn_connection_free(pnc); + //TODO: We've lost the error - we should really propagate it here + pn_proactor_disconnect(proactor_, NULL); + return; + } + connection_context& cc = connection_context::get(pnc); reconnect_context& rc = *cc.reconnect_context_.get(); const reconnect_options::impl& roi = *rc.reconnect_options_->impl_; @@ -318,6 +327,7 @@ bool container::impl::setup_reconnect(pn_connection_t* pnc) { // Schedule reconnect - can do this on container work queue as no one can have the connection // now anyway schedule(delay, make_work(&container::impl::reconnect, this, pnc)); + ++reconnecting_; return true; } @@ -727,6 +737,8 @@ void container::impl::stop(const proton::error_condition& err) { if (stopping_) return; // Already stopping auto_stop_ = true; stopping_ = true; + // Have to wait until actual reconnect to stop or we leak the connection + if (reconnecting_>0) return; } pn_condition_t* error_condition = pn_condition(); set_error_condition(err, error_condition); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5d47e615/proton-c/bindings/cpp/src/proactor_container_impl.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.hpp b/proton-c/bindings/cpp/src/proactor_container_impl.hpp index 06dbcb5..43b695f 100644 --- a/proton-c/bindings/cpp/src/proactor_container_impl.hpp +++ b/proton-c/bindings/cpp/src/proactor_container_impl.hpp @@ -147,6 +147,7 @@ class container::impl { proton::receiver_options receiver_options_; error_condition disconnect_error_; + unsigned reconnecting_; bool auto_stop_; bool stopping_; friend class connector; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5d47e615/proton-c/src/proactor/epoll.c ---------------------------------------------------------------------- diff --git a/proton-c/src/proactor/epoll.c b/proton-c/src/proactor/epoll.c index 5f8c495..4ad2506 100644 --- a/proton-c/src/proactor/epoll.c +++ b/proton-c/src/proactor/epoll.c @@ -2103,6 +2103,8 @@ pn_proactor_t *pn_connection_proactor(pn_connection_t* c) { } void pn_proactor_disconnect(pn_proactor_t *p, pn_condition_t *cond) { + bool notify = false; + lock(&p->context.mutex); // Move the whole contexts list into a disconnecting state pcontext_t *disconnecting_pcontexts = p->contexts; @@ -2115,12 +2117,14 @@ void pn_proactor_disconnect(pn_proactor_t *p, pn_condition_t *cond) { p->disconnects_pending++; ctx = ctx->next; } + notify = wake_if_inactive(p); unlock(&p->context.mutex); - if (!disconnecting_pcontexts) + if (!disconnecting_pcontexts) { + if (notify) wake_notify(&p->context); return; + } // Second pass: different locking, close the pcontexts, free them if !disconnect_ops - bool notify = false; for (ctx = disconnecting_pcontexts; ctx; ctx = ctx->next) { bool do_free = false; bool ctx_notify = true; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5d47e615/proton-c/src/proactor/libuv.c ---------------------------------------------------------------------- diff --git a/proton-c/src/proactor/libuv.c b/proton-c/src/proactor/libuv.c index 5e3c7c2..9329967 100644 --- a/proton-c/src/proactor/libuv.c +++ b/proton-c/src/proactor/libuv.c @@ -989,9 +989,13 @@ static pn_event_batch_t *leader_lead_lh(pn_proactor_t *p, uv_run_mode mode) { /* If disconnect was requested, walk the socket list */ if (p->disconnect) { p->disconnect = false; - uv_mutex_unlock(&p->lock); - uv_walk(&p->loop, on_proactor_disconnect, NULL); - uv_mutex_lock(&p->lock); + if (p->active) { + uv_mutex_unlock(&p->lock); + uv_walk(&p->loop, on_proactor_disconnect, NULL); + uv_mutex_lock(&p->lock); + } else { + p->need_inactive = true; /* Send INACTIVE right away, nothing to do. */ + } } pn_event_batch_t *batch = NULL; for (work_t *w = work_pop(&p->leader_q); w; w = work_pop(&p->leader_q)) { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org