From: Kefu Chai Date: Sat, 1 Oct 2022 08:30:43 +0000 (+0800) Subject: crimson/osd: vendor stop_signal.h X-Git-Tag: v18.1.0~1046^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=815f39295d738bbc6eddd0f8783b245d3caf32e6;p=ceph.git crimson/osd: vendor stop_signal.h stop_signal.h is copied from seastar/apps/lib/stop_signal.hh. this change copies it int our project so we can customize it in a following commit. we will need to add an `abort_source` member to it. the class `stop_signal` works great for us. but under some circumstances, we also need to stop the crimson server programmatically from the server itsef, for instance, per the request of monitor. in that case, `stop_signal` cannot fulfill our needs, as the only thing which can stop it is, SIGTERM or SIGTERM. we could send SIGINT to ourselves to unblock `stop_signal::wait()`. but it would be better if we could leverage `abort_source` for this purpose. for two reasons: * `abort_source` allows use to cancel a "blocking" op. we have a couple background tasks in crimson, like `AdminSocket`'s accept and handle task, which could have been stopped by an `abort_source`. but now it checks for the `stop_gate` before accepting an incoming connection. this pattern cannot be always be repeated. because we cannot *abort* a "blocking" task. for instance, we use a homebrew `tri_mutex` to protect the read/write consistency of an obc, what if the server would need to stop when a request is still trying to acquire the lock? with the help of the `abort_source`, we should be able to either subscribe from the `abort_source`, and set an abort exception for each of the waiters. the same applies to other "blocking" calls like `shared_promise::get_shared_future()`, this allows us to abort the waiter before the promise is resolved. this could be handy if we need to abort potentially op which might take long and should be aborted when monitor wants to kill the osd instance. * `abort_source` allows us to abort the services programmatically. this is the use case mentioned in the beginning of this commit message. Signed-off-by: Kefu Chai --- diff --git a/src/crimson/osd/main.cc b/src/crimson/osd/main.cc index 18fee14aec54..1eead7b924c0 100644 --- a/src/crimson/osd/main.cc +++ b/src/crimson/osd/main.cc @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -27,6 +26,7 @@ #include "crimson/common/fatal_signal.h" #include "crimson/mon/MonClient.h" #include "crimson/net/Messenger.h" +#include "crimson/osd/stop_signal.h" #include "global/pidfile.h" #include "osd.h" diff --git a/src/crimson/osd/stop_signal.h b/src/crimson/osd/stop_signal.h new file mode 100644 index 000000000000..ccc340b13868 --- /dev/null +++ b/src/crimson/osd/stop_signal.h @@ -0,0 +1,79 @@ +/* + * This file is open source software, licensed to you under the terms + * of the Apache License, Version 2.0 (the "License"). See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. You may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Copyright (C) 2020 Cloudius Systems, Ltd. + */ + +#pragma once + +#include +#include +#include + +/// Seastar apps lib namespace + +namespace seastar_apps_lib { + + +/// \brief Futurized SIGINT/SIGTERM signals handler class +/// +/// Seastar-style helper class that allows easy waiting for SIGINT/SIGTERM signals +/// from your app. +/// +/// Example: +/// \code +/// #include +/// ... +/// int main() { +/// ... +/// seastar::thread th([] { +/// seastar_apps_lib::stop_signal stop_signal; +/// +/// stop_signal.wait().get(); // this will wait till we receive SIGINT or SIGTERM signal +/// }); +/// \endcode +class stop_signal { + bool _caught = false; + seastar::condition_variable _cond; +private: + void signaled() { + if (_caught) { + return; + } + _caught = true; + _cond.broadcast(); + } +public: + stop_signal() { + seastar::engine().handle_signal(SIGINT, [this] { signaled(); }); + seastar::engine().handle_signal(SIGTERM, [this] { signaled(); }); + } + ~stop_signal() { + // There's no way to unregister a handler yet, so register a no-op handler instead. + seastar::engine().handle_signal(SIGINT, [] {}); + seastar::engine().handle_signal(SIGTERM, [] {}); + } + seastar::future<> wait() { + return _cond.wait([this] { return _caught; }); + } + bool stopping() const { + return _caught; + } +}; +}