• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "util/crash_report.h"
16 
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 #if defined(_WIN32)
21 #include <windows.h>
22 #endif
23 
24 #if defined(__linux__)
25 
26 #ifndef NETSIM_ANDROID_EMULATOR
27 #include <client/linux/handler/exception_handler.h>
28 #include <fmt/format.h>
29 #include <unwindstack/AndroidUnwinder.h>
30 
31 #include <iostream>
32 #else
33 #include <signal.h>
34 #endif
35 
36 #include <execinfo.h>
37 #include <unistd.h>
38 
39 #include <cstdio>
40 #include <cstdlib>
41 #endif
42 
43 #include "util/filesystem.h"
44 #include "util/ini_file.h"
45 #include "util/log.h"
46 
47 namespace netsim {
48 namespace {
49 
50 #if defined(__linux__)
51 #ifndef NETSIM_ANDROID_EMULATOR
crash_callback(const void * crash_context,size_t crash_context_size,void *)52 bool crash_callback(const void *crash_context, size_t crash_context_size,
53                     void * /* context */) {
54   std::optional<pid_t> tid;
55   std::cerr << "netsimd crash_callback invoked\n";
56   if (crash_context_size >=
57       sizeof(google_breakpad::ExceptionHandler::CrashContext)) {
58     auto *ctx =
59         static_cast<const google_breakpad::ExceptionHandler::CrashContext *>(
60             crash_context);
61     tid = ctx->tid;
62     int signal_number = ctx->siginfo.si_signo;
63     std::cerr << fmt::format("Process crashed, signal: {}[{}], tid: {}\n",
64                              strsignal(signal_number), signal_number, ctx->tid)
65                      .c_str();
66   } else {
67     std::cerr << "Process crashed, signal: unknown, tid: unknown\n";
68   }
69   unwindstack::AndroidLocalUnwinder unwinder;
70   unwindstack::AndroidUnwinderData data;
71   if (!unwinder.Unwind(tid, data)) {
72     std::cerr << "Unwind failed\n";
73     return false;
74   }
75   std::cerr << "Backtrace:\n";
76   for (const auto &frame : data.frames) {
77     std::cerr << fmt::format("{}\n", unwinder.FormatFrame(frame)).c_str();
78   }
79   return true;
80 }
81 #else
82 // Signal handler to print backtraces and then terminate the program.
83 void SignalHandler(int sig) {
84   size_t buffer_size = 20;  // Number of entries in that array.
85   void *buffer[buffer_size];
86 
87   auto size = backtrace(buffer, buffer_size);
88   fprintf(stderr,
89           "netsim error: interrupt by signal %d. Obtained %d stack frames:\n",
90           sig, size);
91   backtrace_symbols_fd(buffer, size, STDERR_FILENO);
92   exit(sig);
93 }
94 #endif
95 #endif
96 
97 }  // namespace
98 
SetUpCrashReport()99 void SetUpCrashReport() {
100 #if defined(__linux__)
101 #ifndef NETSIM_ANDROID_EMULATOR
102   google_breakpad::MinidumpDescriptor descriptor("/tmp");
103   google_breakpad::ExceptionHandler eh(descriptor, nullptr, nullptr, nullptr,
104                                        true, -1);
105   eh.set_crash_handler(crash_callback);
106 #else
107   signal(SIGSEGV, SignalHandler);
108 #endif
109 #endif
110 }
111 
112 }  // namespace netsim
113