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 <memory>
24 #include <optional>
25 #include <string>
26 #include <thread>
27 
28 #include "stack_manager.h"
29 
30 // clang-format off
31 #include <client/linux/handler/exception_handler.h>
32 #include <unwindstack/AndroidUnwinder.h>
33 // clang-format on
34 
35 #include "common/init_flags.h"
36 #include "facade/grpc_root_server.h"
37 #include "hal/hci_hal_host.h"
38 #include "hal/snoop_logger.h"
39 #include "os/log.h"
40 #include "os/parameter_provider.h"
41 #include "os/system_properties.h"
42 
43 using ::bluetooth::ModuleList;
44 using ::bluetooth::StackManager;
45 using ::bluetooth::hal::HciHalHostRootcanalConfig;
46 using ::bluetooth::os::Thread;
47 using namespace bluetooth;
48 
__asan_default_options()49 extern "C" const char* __asan_default_options() {
50   return "detect_container_overflow=0";
51 }
52 
53 namespace {
54 ::bluetooth::facade::GrpcRootServer grpc_root_server;
55 
56 std::promise<void> interrupt_promise;
57 std::future<void> interrupt_future;
58 bool interrupted = false;
59 struct sigaction old_act = {};
interrupt_handler(int signal_number)60 void interrupt_handler(int signal_number) {
61   if (!interrupted) {
62     interrupted = true;
63     log::info(
64         "Stopping gRPC root server due to signal: {}[{}]", strsignal(signal_number), signal_number);
65     interrupt_promise.set_value();
66   } else {
67     log::warn("Already interrupted by signal: {}[{}]", strsignal(signal_number), signal_number);
68   }
69   if (old_act.sa_handler != nullptr && old_act.sa_handler != SIG_IGN && old_act.sa_handler != SIG_DFL) {
70     log::info("Calling saved signal handler");
71     old_act.sa_handler(signal_number);
72   }
73 }
74 struct sigaction new_act = {.sa_handler = interrupt_handler};
75 
crash_callback(const void * crash_context,size_t crash_context_size,void *)76 bool crash_callback(const void* crash_context, size_t crash_context_size, void* /* context */) {
77   std::optional<pid_t> tid;
78   if (crash_context_size >= sizeof(google_breakpad::ExceptionHandler::CrashContext)) {
79     auto* ctx = static_cast<const google_breakpad::ExceptionHandler::CrashContext*>(crash_context);
80     tid = ctx->tid;
81     int signal_number = ctx->siginfo.si_signo;
82     log::error(
83         "Process crashed, signal: {}[{}], tid: {}",
84         strsignal(signal_number),
85         signal_number,
86         ctx->tid);
87   } else {
88     log::error("Process crashed, signal: unknown, tid: unknown");
89   }
90   unwindstack::AndroidLocalUnwinder unwinder;
91   unwindstack::AndroidUnwinderData data;
92   if (!unwinder.Unwind(tid, data)) {
93     log::error("Unwind failed");
94     return false;
95   }
96   log::error("Backtrace:");
97   for (const auto& frame : data.frames) {
98     log::error("{}", unwinder.FormatFrame(frame));
99   }
100   return true;
101 }
102 
103 // Need to stop server on a thread that is not part of a signal handler due to an issue with gRPC
104 // See: https://github.com/grpc/grpc/issues/24884
thread_check_shutdown()105 void thread_check_shutdown() {
106   log::info("shutdown thread waiting for interruption");
107   interrupt_future.wait();
108   log::info("interrupted, stopping server");
109   grpc_root_server.StopServer();
110 }
111 
112 }  // namespace
113 
114 // The entry point for the binary with libbluetooth + facades
main(int argc,const char ** argv)115 int main(int argc, const char** argv) {
116   google_breakpad::MinidumpDescriptor descriptor(google_breakpad::MinidumpDescriptor::kMicrodumpOnConsole);
117   google_breakpad::ExceptionHandler eh(descriptor, nullptr, nullptr, nullptr, true, -1);
118   eh.set_crash_handler(crash_callback);
119 
120   int root_server_port = 8897;
121   int grpc_port = 8899;
122 
123   bluetooth::common::InitFlags::SetAllForTesting();
124 
125   const std::string arg_grpc_root_server_port = "--root-server-port=";
126   const std::string arg_grpc_server_port = "--grpc-port=";
127   const std::string arg_rootcanal_port = "--rootcanal-port=";
128   const std::string arg_btsnoop_path = "--btsnoop=";
129   const std::string arg_btsnooz_path = "--btsnooz=";
130   const std::string arg_btconfig_path = "--btconfig=";
131   for (int i = 1; i < argc; i++) {
132     std::string arg = argv[i];
133     if (arg.find(arg_grpc_root_server_port) == 0) {
134       auto port_number = arg.substr(arg_grpc_root_server_port.size());
135       root_server_port = std::stoi(port_number);
136     }
137     if (arg.find(arg_grpc_server_port) == 0) {
138       auto port_number = arg.substr(arg_grpc_server_port.size());
139       grpc_port = std::stoi(port_number);
140     }
141     if (arg.find(arg_rootcanal_port) == 0) {
142       auto port_number = arg.substr(arg_rootcanal_port.size());
143       HciHalHostRootcanalConfig::Get()->SetPort(std::stoi(port_number));
144     }
145     if (arg.find(arg_btsnoop_path) == 0) {
146       auto btsnoop_path = arg.substr(arg_btsnoop_path.size());
147       ::bluetooth::os::ParameterProvider::OverrideSnoopLogFilePath(btsnoop_path);
148       log::assert_that(
149           ::bluetooth::os::SetSystemProperty(
150               ::bluetooth::hal::SnoopLogger::kBtSnoopLogModeProperty,
151               ::bluetooth::hal::SnoopLogger::kBtSnoopLogModeFull),
152           "assert failed: ::bluetooth::os::SetSystemProperty( "
153           "::bluetooth::hal::SnoopLogger::kBtSnoopLogModeProperty, "
154           "::bluetooth::hal::SnoopLogger::kBtSnoopLogModeFull)");
155     }
156     if (arg.find(arg_btsnooz_path) == 0) {
157       auto btsnooz_path = arg.substr(arg_btsnooz_path.size());
158       ::bluetooth::os::ParameterProvider::OverrideSnoozLogFilePath(btsnooz_path);
159     }
160     if (arg.find(arg_btconfig_path) == 0) {
161       auto btconfig_path = arg.substr(arg_btconfig_path.size());
162       ::bluetooth::os::ParameterProvider::OverrideConfigFilePath(btconfig_path);
163     }
164   }
165 
166   int ret = sigaction(SIGINT, &new_act, &old_act);
167   if (ret < 0) {
168     log::error("sigaction error: {}", strerror(errno));
169   }
170 
171   log::info("Starting Server");
172   grpc_root_server.StartServer("0.0.0.0", root_server_port, grpc_port);
173   log::info("Server started");
174   auto wait_thread = std::thread([] { grpc_root_server.RunGrpcLoop(); });
175   interrupt_future = interrupt_promise.get_future();
176   auto shutdown_thread = std::thread{thread_check_shutdown};
177   wait_thread.join();
178   log::info("Server terminated");
179   shutdown_thread.join();
180   log::info("Shutdown thread terminated");
181 
182   return 0;
183 }
184