This is an automated email from the ASF dual-hosted git repository. guangning pushed a commit to branch branch-2.5 in repository https://gitbox.apache.org/repos/asf/pulsar.git
commit 765aa020d14c50ed3f8a096433777570301a0a63 Author: Nick Rivera <[email protected]> AuthorDate: Thu Feb 13 17:14:39 2020 -0800 [Issue 4070][pulsar-client-cpp] Fix for possible deadlock when closing Pulsar client (#6277) * Attempt at fixing deadlock during client.close() * Fixed formatting * Detach the worker thread in the destructor of ExecutorService if it is still unable to be joined * Possible formatting fixes --- pulsar-client-cpp/lib/ExecutorService.cc | 20 ++++++++++++++------ pulsar-client-cpp/lib/ExecutorService.h | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pulsar-client-cpp/lib/ExecutorService.cc b/pulsar-client-cpp/lib/ExecutorService.cc index 75f465d..8de0459 100644 --- a/pulsar-client-cpp/lib/ExecutorService.cc +++ b/pulsar-client-cpp/lib/ExecutorService.cc @@ -29,7 +29,14 @@ ExecutorService::ExecutorService() work_(new BackgroundWork(*io_service_)), worker_(std::bind(&ExecutorService::startWorker, this, io_service_)) {} -ExecutorService::~ExecutorService() { close(); } +ExecutorService::~ExecutorService() { + close(); + // If the worker_ is still not joinable at this point just detach + // the thread so its destructor does not terminate the app + if (worker_.joinable()) { + worker_.detach(); + } +} void ExecutorService::startWorker(std::shared_ptr<boost::asio::io_service> io_service) { io_service_->run(); } @@ -59,11 +66,12 @@ DeadlineTimerPtr ExecutorService::createDeadlineTimer() { } void ExecutorService::close() { - // Ensure this service has not already been closed. This is - // because worker_.join() is not re-entrant on Windows - if (work_) { - io_service_->stop(); - work_.reset(); + io_service_->stop(); + work_.reset(); + // If this thread is attempting to join itself, do not. The destructor's + // call to close will handle joining if it does not occur here. This also ensures + // join is not called twice since it is not re-entrant on windows + if (std::this_thread::get_id() != worker_.get_id() && worker_.joinable()) { worker_.join(); } } diff --git a/pulsar-client-cpp/lib/ExecutorService.h b/pulsar-client-cpp/lib/ExecutorService.h index 883d4ce..b673b79 100644 --- a/pulsar-client-cpp/lib/ExecutorService.h +++ b/pulsar-client-cpp/lib/ExecutorService.h @@ -70,7 +70,7 @@ class PULSAR_PUBLIC ExecutorService : private boost::noncopyable { * background invoking async handlers as they are finished and result is available from * io_service */ - boost::asio::detail::thread worker_; + std::thread worker_; }; typedef std::shared_ptr<ExecutorService> ExecutorServicePtr;
