@@ -54,19 +54,34 @@ static entity_addr_t get_server_addr() {
5454 return saddr;
5555}
5656
57+ /*
58+ * at_exit() is now deprecated, and Seastar recommends using deferred_stop()
59+ * as an alternative for object cleanup.
60+ *
61+ * However, in our use case, deferred_stop() is not a suitable replacement
62+ * due to differences in how it manages object lifetimes.
63+ *
64+ * Previously, at_exit() captured the sharded_obj and kept it alive until shutdown.
65+ * In contrast, deferred_stop() does not retain ownership and assumes the referenced
66+ * object remains valid for the lifetime of the deferred_stop instance.
67+ *
68+ * To address this, we introduced a static list to retain each sharded_obj
69+ * created via create_sharded().
70+ */
71+
72+ template <typename T>
73+ static std::list<seastar::lw_shared_ptr<seastar::sharded<T>>> sharded_objects;
74+
5775template <typename T, typename ... Args>
5876seastar::future<T*> create_sharded (Args... args) {
5977 // we should only construct/stop shards on #0
60- return seastar::smp::submit_to (0 , [=] {
78+ return seastar::smp::submit_to (0 , [=]() -> seastar::future<seastar::sharded<T>*> {
6179 auto sharded_obj = seastar::make_lw_shared<seastar::sharded<T>>();
62- return sharded_obj->start (args...
63- ).then ([sharded_obj] {
64- seastar::engine ().at_exit ([sharded_obj] {
65- return sharded_obj->stop ().then ([sharded_obj] {});
66- });
80+ sharded_objects<T>.push_back (sharded_obj);
81+ return sharded_obj->start (args...).then ([sharded_obj] {
6782 return sharded_obj.get ();
6883 });
69- }).then ([](seastar::sharded<T> * ptr_shard) {
84+ }).then ([](seastar::sharded<T>* ptr_shard) {
7085 return &ptr_shard->local ();
7186 });
7287}
@@ -390,6 +405,15 @@ static seastar::future<> test_echo(unsigned rounds,
390405 }).handle_exception ([](auto eptr) {
391406 logger ().error (" test_echo() failed: got exception {}" , eptr);
392407 throw ;
408+ }).then ([] {
409+ return seastar::smp::submit_to (0 , [] {
410+ return seastar::do_for_each (sharded_objects<test_state::Client>,
411+ [](auto & sharded_obj) {
412+ return sharded_obj->stop ();
413+ });
414+ }).then ([] {
415+ sharded_objects<test_state::Client>.clear ();
416+ });
393417 }).finally ([gates, server1, server2] {
394418 return gates->close ();
395419 });
@@ -3832,6 +3856,15 @@ seastar::future<int> do_test(seastar::app_template& app)
38323856 // which will result in memory leak and thus fail LeakSanitizer.
38333857 return seastar::sleep (100ms);
38343858 });
3859+ }).then ([] {
3860+ return seastar::smp::submit_to (0 , [] {
3861+ return seastar::do_for_each (sharded_objects<ShardedGates>,
3862+ [](auto & sharded_obj) {
3863+ return sharded_obj->stop ();
3864+ });
3865+ }).then ([] {
3866+ sharded_objects<ShardedGates>.clear ();
3867+ });
38353868 }).then ([] {
38363869 return crimson::common::sharded_conf ().stop ();
38373870 }).then ([] {
0 commit comments