Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions lib/ClientImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,8 @@ void ClientImpl::closeAsync(const CloseCallback& callback) {
auto producers = producers_.move();
auto consumers = consumers_.move();

SharedInt numberOfOpenHandlers = std::make_shared<int>(producers.size() + consumers.size());
SharedInt numberOfOpenHandlers =
std::make_shared<std::atomic<int>>(static_cast<int>(producers.size() + consumers.size()));
LOG_INFO("Closing Pulsar client with " << producers.size() << " producers and " << consumers.size()
<< " consumers");

Expand Down Expand Up @@ -896,10 +897,13 @@ void ClientImpl::handleClose(Result result, const SharedInt& numberOfOpenHandler
<< expected << ". This means multiple errors have occurred while closing the client");
}

if (*numberOfOpenHandlers > 0) {
--(*numberOfOpenHandlers);
// Decrement the counter atomically and let only the call that observes it reaching zero proceed,
// otherwise concurrent close callbacks may race on the counter and both (or neither) shut down.
int remaining = numberOfOpenHandlers->load(std::memory_order_acquire);
while (remaining > 0 && !numberOfOpenHandlers->compare_exchange_weak(remaining, remaining - 1,
std::memory_order_acq_rel)) {
}
if (*numberOfOpenHandlers == 0) {
if (remaining <= 1) {
std::unique_lock lock(mutex_);
if (state_ == Closed) {
LOG_DEBUG("Client is already shutting down, possible race condition in handleClose");
Expand Down
2 changes: 1 addition & 1 deletion lib/ClientImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class ClientImpl : public std::enable_shared_from_this<ClientImpl> {
void handleConsumerCreated(Result result, const ConsumerImplBaseWeakPtr& consumerWeakPtr,
const SubscribeV2Callback& callback, const ConsumerImplBasePtr& consumer);

typedef std::shared_ptr<int> SharedInt;
typedef std::shared_ptr<std::atomic<int>> SharedInt;

void handleClose(Result result, const SharedInt& remaining, const ResultCallback& callback);

Expand Down