Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add seastar signal api #2384

Closed

Conversation

tomershafir
Copy link
Contributor

@tomershafir tomershafir commented Aug 4, 2024

fixes: #261.

The PR adds an object based interface for signals on seastar namespace.

  • Adds signal.hh header implemented by reactor.cc.
  • Adds doc/signal.md.
  • Deprecates reactor::handle_signal.
  • Supports C++20 modules.

Future possibilities:

  • Add signal handler unset logic, and unset signal handler on destructor.
  • Consider to add a reliable test case for once (should require reactor changes to expose an indicator).

@tomershafir tomershafir marked this pull request as ready for review August 4, 2024 09:25
@xemul
Copy link
Contributor

xemul commented Aug 7, 2024

@tomershafir , please fix the commits sequence, it contains some "Merge branch 'master'" and a post-fixlet, both are not welcome

@tomershafir tomershafir force-pushed the add-seastar-signal-api branch 2 times, most recently from f9bdcc2 to 1834cb5 Compare August 7, 2024 06:47
doc/signal.md Outdated

You need to construct a `signal_handler` instance that will register the provided signal handler for the specified signal based on the configuration params.

At the moment, the signal handler will remain past object destruction.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's extremely confusing. I would expect that desctruction of an object unregisters the handler

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ill add unregister logic to this PR

void handle_signal(int signo, noncopyable_function<void ()>&& handler);
void wakeup();
/// @private
bool stopped() const noexcept { return _stopped; }

private:
class signals {
struct _signal_handler {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leading underscore is for private members, class names shouldn't have it

friend class thread_pool;
friend class thread_context;
friend class internal::cpu_stall_detector;
friend struct signal_handler;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New friends for reactor class are not welcome. It's large enough already

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other ways would be:

  1. Add public reactor::handle_signal_once and undo deprecation of reactor::handle_signal. Users will be able to call them and I think it inverts the purpose of changing the api. Also, it adds more code to the reactor.
  2. Refactor signal logic out of the reactor. It seems like the blast radius is big and it's not an easy task.

Thus I would prefer the friend struct solution at the moment. Let me know wdyt

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have nested class signal, public nested class signal_handler would be nice replacement for explicit friend. But as I wrote above, installing handler in constructor smells like RAII and implies unsetting it in destructor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My goal has been to add a clean seastar namespace level api, not through the reactor.

@tomershafir
Copy link
Contributor Author

@xemul Regarding destructor logic, it seems to me like the RAII approach here may be less suitable. As the POSIX api doesn't fit RAII naturally, adapting it can introduce complexity and confusion. I assume that multiple objects can be constructed for a single signo, like POSIX.

For example:

seastar::signal_handler signal_handler1(SIGINT, [this] { signaled(); });
...
seastar::signal_handler signal_handler2(SIGINT, [this] { signaled(); });
...

What should happen if signal_handler1 is destroyed after signal_handler2 is constructed and before it's destroyed?
What should happen if signal_handler1 is destroyed after signal_handler2 is destroyed?
The possible solutions to these problems don't seem natural for RAII to me.

I think I should re-target this PR to introduce a clean seastar namespace level api, and do it via procedures rather than objects. Wdyt?

@xemul
Copy link
Contributor

xemul commented Aug 15, 2024

I think I should re-target this PR to introduce a clean seastar namespace level api, and do it via procedures rather than objects. Wdyt?

Yes, this sounds good

@tomershafir
Copy link
Contributor Author

@xemul I force pushed the changes

@@ -20,6 +20,7 @@
*/

#include <seastar/core/reactor.hh>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this header still needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, will remove

signals _signals;
std::unique_ptr<thread_pool> _thread_pool;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change

};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unwanted indentation

noncopyable_function<void ()> _handler;
};
std::atomic<uint64_t> _pending_signals;
std::unordered_map<int, signal_handler> _signal_handlers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this block moved upwards?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove redundant private in a class

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ill extract it into a different PR

namespace seastar {

static reactor& engine_or_throw() {
if (!engine_is_ready()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's impossible. No tasks can be run until engine is ready

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its possible, if a user calls the procedure before app.run(), like:

seastar::handle_signal(SIGINT, [] {});
return app.run(argc, argv, [&app] -> seastar::future<> {
...

I dont think its obvious that it must be called inside run(), so I think the logic provides a more controlled and understandable error handling.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case the "reactor must be initialized" can be confusing message, because it's not obvious that "app.run()" initializes the reactor. I would just mention in the method doc, that it's only valid to use one from inside app.run() lambda, otherwise it's UB

@tomershafir tomershafir force-pushed the add-seastar-signal-api branch 2 times, most recently from 795134e to 01aa880 Compare August 22, 2024 13:26
@tomershafir tomershafir requested a review from xemul August 22, 2024 13:42
@@ -31,15 +31,8 @@ module seastar;

namespace seastar {

static reactor& engine_or_throw() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, squash it with the previous commit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, done

@tomershafir
Copy link
Contributor Author

@xemul close #261?

@tomershafir tomershafir deleted the add-seastar-signal-api branch August 30, 2024 06:59
niekbouman pushed a commit to niekbouman/seastar that referenced this pull request Sep 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Seastar shouldn't always traps SIGINT and SIGTERM
2 participants