diff --git a/hazelcast/include/hazelcast/client/HazelcastClient.h b/hazelcast/include/hazelcast/client/HazelcastClient.h index c4cbf5c529..f416f3e284 100644 --- a/hazelcast/include/hazelcast/client/HazelcastClient.h +++ b/hazelcast/include/hazelcast/client/HazelcastClient.h @@ -713,6 +713,7 @@ namespace hazelcast { ClientConfig clientConfig; ClientProperties clientProperties; + util::CountDownLatch shutdownLatch; spi::ClientContext clientContext; spi::LifecycleService lifecycleService; serialization::pimpl::SerializationService serializationService; diff --git a/hazelcast/include/hazelcast/client/spi/LifecycleService.h b/hazelcast/include/hazelcast/client/spi/LifecycleService.h index 625c1660c9..0412212043 100644 --- a/hazelcast/include/hazelcast/client/spi/LifecycleService.h +++ b/hazelcast/include/hazelcast/client/spi/LifecycleService.h @@ -46,7 +46,8 @@ namespace hazelcast { class HAZELCAST_API LifecycleService { public: - LifecycleService(ClientContext &clientContext, const ClientConfig &clientConfig); + LifecycleService(ClientContext &clientContext, const ClientConfig &clientConfig, + util::CountDownLatch &shutdownLatch); virtual ~LifecycleService(); @@ -68,7 +69,7 @@ namespace hazelcast { std::set listeners; util::Mutex listenerLock; util::AtomicBoolean active; - util::CountDownLatch shutdownLatch; + util::CountDownLatch &shutdownLatch; }; } diff --git a/hazelcast/src/hazelcast/client/HazelcastClient.cpp b/hazelcast/src/hazelcast/client/HazelcastClient.cpp index 944a53d48f..7000047479 100644 --- a/hazelcast/src/hazelcast/client/HazelcastClient.cpp +++ b/hazelcast/src/hazelcast/client/HazelcastClient.cpp @@ -35,8 +35,9 @@ namespace hazelcast { HazelcastClient::HazelcastClient(ClientConfig &config) : clientConfig(config) , clientProperties(config) + , shutdownLatch(1) , clientContext(*this) - , lifecycleService(clientContext, clientConfig) + , lifecycleService(clientContext, clientConfig, shutdownLatch) , serializationService(config.getSerializationConfig()) , connectionManager(new connection::ConnectionManager(clientContext, clientConfig.isSmart())) , nearCacheManager(serializationService) @@ -65,6 +66,12 @@ namespace hazelcast { HazelcastClient::~HazelcastClient() { lifecycleService.shutdown(); + /** + * We can not depend on the destruction order of the variables. lifecycleService may be destructed later + * than the clientContext which is accessed by different service threads, hence we need to explicitly wait + * for shutdown completion. + */ + shutdownLatch.await(); } diff --git a/hazelcast/src/hazelcast/client/spi/LifecycleService.cpp b/hazelcast/src/hazelcast/client/spi/LifecycleService.cpp index 08edb1f7e6..bc33264a0e 100644 --- a/hazelcast/src/hazelcast/client/spi/LifecycleService.cpp +++ b/hazelcast/src/hazelcast/client/spi/LifecycleService.cpp @@ -31,12 +31,12 @@ namespace hazelcast { namespace client { namespace spi { - LifecycleService::LifecycleService(ClientContext &clientContext, const ClientConfig &clientConfig) + LifecycleService::LifecycleService(ClientContext &clientContext, const ClientConfig &clientConfig, + util::CountDownLatch &shutdownLatch) :clientContext(clientContext) - , active(true), shutdownLatch(1) { + , active(true), shutdownLatch(shutdownLatch) { std::set const &lifecycleListeners = clientConfig.getLifecycleListeners(); listeners.insert(lifecycleListeners.begin(), lifecycleListeners.end()); - } bool LifecycleService::start() {