Skip to content

Commit eefe659

Browse files
committed
reactor: deprecate at_exit()
at_exit() tasks are unordered with respect to each other, so are not very useful. Since they are public, we can't remove them outright, but prepare by deprecating the public interface. Internal users are converted to a private interface. An explanation about how to use seastar::app_template is added to the documentation.
1 parent 232ffaf commit eefe659

File tree

5 files changed

+33
-9
lines changed

5 files changed

+33
-9
lines changed

Diff for: apps/io_tester/io_tester.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,7 @@ int main(int ac, char** av) {
11751175
}
11761176

11771177
ctx.start(storage, *st_type, reqs, duration).get();
1178-
engine().at_exit([&ctx] {
1178+
internal::at_exit([&ctx] {
11791179
return ctx.stop();
11801180
});
11811181
std::cout << "Creating initial files..." << std::endl;

Diff for: apps/memcached/memcache.cc

+4-4
Original file line numberDiff line numberDiff line change
@@ -1454,10 +1454,10 @@ int main(int ac, char** av) {
14541454
;
14551455

14561456
return app.run_deprecated(ac, av, [&] {
1457-
engine().at_exit([&] { return tcp_server.stop(); });
1458-
engine().at_exit([&] { return udp_server.stop(); });
1459-
engine().at_exit([&] { return cache_peers.stop(); });
1460-
engine().at_exit([&] { return system_stats.stop(); });
1457+
internal::at_exit([&] { return tcp_server.stop(); });
1458+
internal::at_exit([&] { return udp_server.stop(); });
1459+
internal::at_exit([&] { return cache_peers.stop(); });
1460+
internal::at_exit([&] { return system_stats.stop(); });
14611461

14621462
auto&& config = app.configuration();
14631463
uint16_t port = config["port"].as<uint16_t>();

Diff for: include/seastar/core/reactor.hh

+17-1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ void increase_thrown_exceptions_counter() noexcept;
132132
template <typename Func>
133133
void at_destroy(Func&& func);
134134

135+
void at_exit(noncopyable_function<future<> ()> func);
136+
135137
}
136138

137139
class io_queue;
@@ -167,6 +169,7 @@ private:
167169
class execution_stage_pollfn;
168170
template <typename Func>
169171
friend void internal::at_destroy(Func&&);
172+
friend void internal::at_exit(noncopyable_function<future<> ()> func);
170173
friend class manual_clock;
171174
friend class file_data_source_impl; // for fstream statistics
172175
friend class internal::reactor_stall_sampler;
@@ -528,6 +531,18 @@ public:
528531
return _stop_requested.wait(timeout, [this] { return _stopping; });
529532
}
530533

534+
/// Deprecated. Use following sequence instead:
535+
///
536+
/// ```
537+
/// return seastar::app_template::run([] {
538+
/// return seastar::async([] {
539+
/// // Since the function runs in a thread, it can wait for futures using
540+
/// // future::get().
541+
/// auto deferred_task = defer(/* the function you want to run at exit */);
542+
/// });
543+
/// });
544+
/// ```
545+
[[deprecated("Use seastar::app_template::run(), seastar::async(), and seastar::defer() for orderly shutdown")]]
531546
void at_exit(noncopyable_function<future<> ()> func);
532547

533548
/// Deprecated. Use following sequence instead:
@@ -545,7 +560,8 @@ public:
545560
do_at_destroy(std::forward<Func>(func));
546561
}
547562
private:
548-
template <typename Func>
563+
void do_at_exit(noncopyable_function<future<> ()> func);
564+
template <typename Func>
549565
void do_at_destroy(Func&& func) {
550566
_at_destroy_tasks->_q.push_back(make_task(default_scheduling_group(), std::forward<Func>(func)));
551567
}

Diff for: src/core/app-template.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ int
166166
app_template::run(int ac, char ** av, std::function<future<int> ()>&& func) noexcept {
167167
return run_deprecated(ac, av, [func = std::move(func)] () mutable {
168168
auto func_done = make_lw_shared<promise<>>();
169-
engine().at_exit([func_done] { return func_done->get_future(); });
169+
internal::at_exit([func_done] { return func_done->get_future(); });
170170
// No need to wait for this future.
171171
// func's returned exit_code is communicated via engine().exit()
172172
(void)futurize_invoke(func).finally([func_done] {

Diff for: src/core/reactor.cc

+10-2
Original file line numberDiff line numberDiff line change
@@ -2426,11 +2426,19 @@ void reactor::del_timer(timer<manual_clock>* tmr) noexcept {
24262426
_manual_timers.remove(*tmr, _expired_manual_timers);
24272427
}
24282428

2429-
void reactor::at_exit(noncopyable_function<future<> ()> func) {
2429+
void reactor::do_at_exit(noncopyable_function<future<> ()> func) {
24302430
SEASTAR_ASSERT(!_stopping);
24312431
_exit_funcs.push_back(std::move(func));
24322432
}
24332433

2434+
void reactor::at_exit(noncopyable_function<future<> ()> func) {
2435+
do_at_exit(std::move(func));
2436+
}
2437+
2438+
void internal::at_exit(noncopyable_function<future<> ()> func) {
2439+
engine().do_at_exit(std::move(func));
2440+
}
2441+
24342442
future<> reactor::run_exit_tasks() {
24352443
_stop_requested.broadcast();
24362444
stop_aio_eventfd_loop();
@@ -2954,7 +2962,7 @@ void reactor::start_aio_eventfd_loop() {
29542962
});
29552963
});
29562964
// must use make_lw_shared, because at_exit expects a copyable function
2957-
at_exit([loop_done = make_lw_shared(std::move(loop_done))] {
2965+
do_at_exit([loop_done = make_lw_shared(std::move(loop_done))] {
29582966
return std::move(*loop_done);
29592967
});
29602968
}

0 commit comments

Comments
 (0)