1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <bluetooth/log.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20
21 #include <csignal>
22 #include <cstring>
23 #include <optional>
24 #include <string>
25 #include <thread>
26
27 #include "stack_manager.h"
28
29 // clang-format off
30 #include <client/linux/handler/exception_handler.h>
31 #include <unwindstack/AndroidUnwinder.h>
32 // clang-format on
33
34 #include "facade/grpc_root_server.h"
35 #include "hal/hci_hal_host.h"
36 #include "hal/snoop_logger.h"
37 #include "os/parameter_provider.h"
38 #include "os/system_properties.h"
39
40 using ::bluetooth::ModuleList;
41 using ::bluetooth::StackManager;
42 using ::bluetooth::hal::HciHalHostRootcanalConfig;
43 using ::bluetooth::os::Thread;
44 using namespace bluetooth;
45
__asan_default_options()46 extern "C" const char* __asan_default_options() { return "detect_container_overflow=0"; }
47
48 namespace {
49 ::bluetooth::facade::GrpcRootServer grpc_root_server;
50
51 std::promise<void> interrupt_promise;
52 std::future<void> interrupt_future;
53 bool interrupted = false;
54 struct sigaction old_act = {};
interrupt_handler(int signal_number)55 void interrupt_handler(int signal_number) {
56 if (!interrupted) {
57 interrupted = true;
58 log::info("Stopping gRPC root server due to signal: {}[{}]", strsignal(signal_number),
59 signal_number);
60 interrupt_promise.set_value();
61 } else {
62 log::warn("Already interrupted by signal: {}[{}]", strsignal(signal_number), signal_number);
63 }
64 if (old_act.sa_handler != nullptr && old_act.sa_handler != SIG_IGN &&
65 old_act.sa_handler != SIG_DFL) {
66 log::info("Calling saved signal handler");
67 old_act.sa_handler(signal_number);
68 }
69 }
70 struct sigaction new_act = {.sa_handler = interrupt_handler};
71
crash_callback(const void * crash_context,size_t crash_context_size,void *)72 bool crash_callback(const void* crash_context, size_t crash_context_size, void* /* context */) {
73 std::optional<pid_t> tid;
74 if (crash_context_size >= sizeof(google_breakpad::ExceptionHandler::CrashContext)) {
75 auto* ctx = static_cast<const google_breakpad::ExceptionHandler::CrashContext*>(crash_context);
76 tid = ctx->tid;
77 int signal_number = ctx->siginfo.si_signo;
78 log::error("Process crashed, signal: {}[{}], tid: {}", strsignal(signal_number), signal_number,
79 ctx->tid);
80 } else {
81 log::error("Process crashed, signal: unknown, tid: unknown");
82 }
83 unwindstack::AndroidLocalUnwinder unwinder;
84 unwindstack::AndroidUnwinderData data;
85 if (!unwinder.Unwind(tid, data)) {
86 log::error("Unwind failed");
87 return false;
88 }
89 log::error("Backtrace:");
90 for (const auto& frame : data.frames) {
91 log::error("{}", unwinder.FormatFrame(frame));
92 }
93 return true;
94 }
95
96 // Need to stop server on a thread that is not part of a signal handler due to an issue with gRPC
97 // See: https://github.com/grpc/grpc/issues/24884
thread_check_shutdown()98 void thread_check_shutdown() {
99 log::info("shutdown thread waiting for interruption");
100 interrupt_future.wait();
101 log::info("interrupted, stopping server");
102 grpc_root_server.StopServer();
103 }
104
105 } // namespace
106
107 // The entry point for the binary with libbluetooth + facades
main(int argc,const char ** argv)108 int main(int argc, const char** argv) {
109 google_breakpad::MinidumpDescriptor descriptor(
110 google_breakpad::MinidumpDescriptor::kMicrodumpOnConsole);
111 google_breakpad::ExceptionHandler eh(descriptor, nullptr, nullptr, nullptr, true, -1);
112 eh.set_crash_handler(crash_callback);
113
114 int root_server_port = 8897;
115 int grpc_port = 8899;
116
117 const std::string arg_grpc_root_server_port = "--root-server-port=";
118 const std::string arg_grpc_server_port = "--grpc-port=";
119 const std::string arg_rootcanal_port = "--rootcanal-port=";
120 const std::string arg_btsnoop_path = "--btsnoop=";
121 const std::string arg_btsnooz_path = "--btsnooz=";
122 const std::string arg_btconfig_path = "--btconfig=";
123 for (int i = 1; i < argc; i++) {
124 std::string arg = argv[i];
125 if (arg.find(arg_grpc_root_server_port) == 0) {
126 auto port_number = arg.substr(arg_grpc_root_server_port.size());
127 root_server_port = std::stoi(port_number);
128 }
129 if (arg.find(arg_grpc_server_port) == 0) {
130 auto port_number = arg.substr(arg_grpc_server_port.size());
131 grpc_port = std::stoi(port_number);
132 }
133 if (arg.find(arg_rootcanal_port) == 0) {
134 auto port_number = arg.substr(arg_rootcanal_port.size());
135 HciHalHostRootcanalConfig::Get()->SetPort(std::stoi(port_number));
136 }
137 if (arg.find(arg_btsnoop_path) == 0) {
138 auto btsnoop_path = arg.substr(arg_btsnoop_path.size());
139 ::bluetooth::os::ParameterProvider::OverrideSnoopLogFilePath(btsnoop_path);
140 log::assert_that(::bluetooth::os::SetSystemProperty(
141 ::bluetooth::hal::SnoopLogger::kBtSnoopLogModeProperty,
142 ::bluetooth::hal::SnoopLogger::kBtSnoopLogModeFull),
143 "assert failed: ::bluetooth::os::SetSystemProperty( "
144 "::bluetooth::hal::SnoopLogger::kBtSnoopLogModeProperty, "
145 "::bluetooth::hal::SnoopLogger::kBtSnoopLogModeFull)");
146 }
147 if (arg.find(arg_btsnooz_path) == 0) {
148 auto btsnooz_path = arg.substr(arg_btsnooz_path.size());
149 ::bluetooth::os::ParameterProvider::OverrideSnoozLogFilePath(btsnooz_path);
150 }
151 if (arg.find(arg_btconfig_path) == 0) {
152 auto btconfig_path = arg.substr(arg_btconfig_path.size());
153 ::bluetooth::os::ParameterProvider::OverrideConfigFilePath(btconfig_path);
154 }
155 }
156
157 int ret = sigaction(SIGINT, &new_act, &old_act);
158 if (ret < 0) {
159 log::error("sigaction error: {}", strerror(errno));
160 }
161
162 log::info("Starting Server");
163 grpc_root_server.StartServer("0.0.0.0", root_server_port, grpc_port);
164 log::info("Server started");
165 auto wait_thread = std::thread([] { grpc_root_server.RunGrpcLoop(); });
166 interrupt_future = interrupt_promise.get_future();
167 auto shutdown_thread = std::thread{thread_check_shutdown};
168 wait_thread.join();
169 log::info("Server terminated");
170 shutdown_thread.join();
171 log::info("Shutdown thread terminated");
172
173 return 0;
174 }
175