/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * 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. */ #include #include #include #include #include #include #include #include #include "stack_manager.h" // clang-format off #include #include // clang-format on #include "facade/grpc_root_server.h" #include "hal/hci_hal_host.h" #include "hal/snoop_logger.h" #include "os/parameter_provider.h" #include "os/system_properties.h" using ::bluetooth::ModuleList; using ::bluetooth::StackManager; using ::bluetooth::hal::HciHalHostRootcanalConfig; using ::bluetooth::os::Thread; using namespace bluetooth; extern "C" const char* __asan_default_options() { return "detect_container_overflow=0"; } namespace { ::bluetooth::facade::GrpcRootServer grpc_root_server; std::promise interrupt_promise; std::future interrupt_future; bool interrupted = false; struct sigaction old_act = {}; void interrupt_handler(int signal_number) { if (!interrupted) { interrupted = true; log::info("Stopping gRPC root server due to signal: {}[{}]", strsignal(signal_number), signal_number); interrupt_promise.set_value(); } else { log::warn("Already interrupted by signal: {}[{}]", strsignal(signal_number), signal_number); } if (old_act.sa_handler != nullptr && old_act.sa_handler != SIG_IGN && old_act.sa_handler != SIG_DFL) { log::info("Calling saved signal handler"); old_act.sa_handler(signal_number); } } struct sigaction new_act = {.sa_handler = interrupt_handler}; bool crash_callback(const void* crash_context, size_t crash_context_size, void* /* context */) { std::optional tid; if (crash_context_size >= sizeof(google_breakpad::ExceptionHandler::CrashContext)) { auto* ctx = static_cast(crash_context); tid = ctx->tid; int signal_number = ctx->siginfo.si_signo; log::error("Process crashed, signal: {}[{}], tid: {}", strsignal(signal_number), signal_number, ctx->tid); } else { log::error("Process crashed, signal: unknown, tid: unknown"); } unwindstack::AndroidLocalUnwinder unwinder; unwindstack::AndroidUnwinderData data; if (!unwinder.Unwind(tid, data)) { log::error("Unwind failed"); return false; } log::error("Backtrace:"); for (const auto& frame : data.frames) { log::error("{}", unwinder.FormatFrame(frame)); } return true; } // Need to stop server on a thread that is not part of a signal handler due to an issue with gRPC // See: https://github.com/grpc/grpc/issues/24884 void thread_check_shutdown() { log::info("shutdown thread waiting for interruption"); interrupt_future.wait(); log::info("interrupted, stopping server"); grpc_root_server.StopServer(); } } // namespace // The entry point for the binary with libbluetooth + facades int main(int argc, const char** argv) { google_breakpad::MinidumpDescriptor descriptor( google_breakpad::MinidumpDescriptor::kMicrodumpOnConsole); google_breakpad::ExceptionHandler eh(descriptor, nullptr, nullptr, nullptr, true, -1); eh.set_crash_handler(crash_callback); int root_server_port = 8897; int grpc_port = 8899; const std::string arg_grpc_root_server_port = "--root-server-port="; const std::string arg_grpc_server_port = "--grpc-port="; const std::string arg_rootcanal_port = "--rootcanal-port="; const std::string arg_btsnoop_path = "--btsnoop="; const std::string arg_btsnooz_path = "--btsnooz="; const std::string arg_btconfig_path = "--btconfig="; for (int i = 1; i < argc; i++) { std::string arg = argv[i]; if (arg.find(arg_grpc_root_server_port) == 0) { auto port_number = arg.substr(arg_grpc_root_server_port.size()); root_server_port = std::stoi(port_number); } if (arg.find(arg_grpc_server_port) == 0) { auto port_number = arg.substr(arg_grpc_server_port.size()); grpc_port = std::stoi(port_number); } if (arg.find(arg_rootcanal_port) == 0) { auto port_number = arg.substr(arg_rootcanal_port.size()); HciHalHostRootcanalConfig::Get()->SetPort(std::stoi(port_number)); } if (arg.find(arg_btsnoop_path) == 0) { auto btsnoop_path = arg.substr(arg_btsnoop_path.size()); ::bluetooth::os::ParameterProvider::OverrideSnoopLogFilePath(btsnoop_path); log::assert_that(::bluetooth::os::SetSystemProperty( ::bluetooth::hal::SnoopLogger::kBtSnoopLogModeProperty, ::bluetooth::hal::SnoopLogger::kBtSnoopLogModeFull), "assert failed: ::bluetooth::os::SetSystemProperty( " "::bluetooth::hal::SnoopLogger::kBtSnoopLogModeProperty, " "::bluetooth::hal::SnoopLogger::kBtSnoopLogModeFull)"); } if (arg.find(arg_btsnooz_path) == 0) { auto btsnooz_path = arg.substr(arg_btsnooz_path.size()); ::bluetooth::os::ParameterProvider::OverrideSnoozLogFilePath(btsnooz_path); } if (arg.find(arg_btconfig_path) == 0) { auto btconfig_path = arg.substr(arg_btconfig_path.size()); ::bluetooth::os::ParameterProvider::OverrideConfigFilePath(btconfig_path); } } int ret = sigaction(SIGINT, &new_act, &old_act); if (ret < 0) { log::error("sigaction error: {}", strerror(errno)); } log::info("Starting Server"); grpc_root_server.StartServer("0.0.0.0", root_server_port, grpc_port); log::info("Server started"); auto wait_thread = std::thread([] { grpc_root_server.RunGrpcLoop(); }); interrupt_future = interrupt_promise.get_future(); auto shutdown_thread = std::thread{thread_check_shutdown}; wait_thread.join(); log::info("Server terminated"); shutdown_thread.join(); log::info("Shutdown thread terminated"); return 0; }