xref: /aosp_15_r20/external/fbjni/cxx/lyra/lyra_exceptions.cpp (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1*65c59e02SInna Palant /*
2*65c59e02SInna Palant  * Copyright (c) Facebook, Inc. and its affiliates.
3*65c59e02SInna Palant  *
4*65c59e02SInna Palant  * Licensed under the Apache License, Version 2.0 (the "License");
5*65c59e02SInna Palant  * you may not use this file except in compliance with the License.
6*65c59e02SInna Palant  * You may obtain a copy of the License at
7*65c59e02SInna Palant  *
8*65c59e02SInna Palant  *     http://www.apache.org/licenses/LICENSE-2.0
9*65c59e02SInna Palant  *
10*65c59e02SInna Palant  * Unless required by applicable law or agreed to in writing, software
11*65c59e02SInna Palant  * distributed under the License is distributed on an "AS IS" BASIS,
12*65c59e02SInna Palant  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*65c59e02SInna Palant  * See the License for the specific language governing permissions and
14*65c59e02SInna Palant  * limitations under the License.
15*65c59e02SInna Palant  */
16*65c59e02SInna Palant 
17*65c59e02SInna Palant #include <lyra/lyra_exceptions.h>
18*65c59e02SInna Palant 
19*65c59e02SInna Palant #include <cstdlib>
20*65c59e02SInna Palant #include <exception>
21*65c59e02SInna Palant #include <sstream>
22*65c59e02SInna Palant #include <typeinfo>
23*65c59e02SInna Palant 
24*65c59e02SInna Palant #include <fbjni/detail/Log.h>
25*65c59e02SInna Palant 
26*65c59e02SInna Palant namespace facebook {
27*65c59e02SInna Palant namespace lyra {
28*65c59e02SInna Palant 
29*65c59e02SInna Palant using namespace detail;
30*65c59e02SInna Palant 
31*65c59e02SInna Palant namespace {
32*65c59e02SInna Palant std::terminate_handler gTerminateHandler;
33*65c59e02SInna Palant 
logExceptionAndAbort()34*65c59e02SInna Palant void logExceptionAndAbort() {
35*65c59e02SInna Palant   if (auto ptr = std::current_exception()) {
36*65c59e02SInna Palant     FBJNI_LOGE("Uncaught exception: %s", toString(ptr).c_str());
37*65c59e02SInna Palant #ifndef _WIN32
38*65c59e02SInna Palant     auto trace = getExceptionTraceHolder(ptr);
39*65c59e02SInna Palant     if (trace) {
40*65c59e02SInna Palant       logStackTrace(getStackTraceSymbols(trace->stackTrace_));
41*65c59e02SInna Palant     }
42*65c59e02SInna Palant #endif
43*65c59e02SInna Palant   }
44*65c59e02SInna Palant   if (gTerminateHandler) {
45*65c59e02SInna Palant     gTerminateHandler();
46*65c59e02SInna Palant   } else {
47*65c59e02SInna Palant     FBJNI_LOGF("Uncaught exception and no gTerminateHandler set");
48*65c59e02SInna Palant   }
49*65c59e02SInna Palant }
50*65c59e02SInna Palant 
51*65c59e02SInna Palant } // namespace
52*65c59e02SInna Palant 
~ExceptionTraceHolder()53*65c59e02SInna Palant ExceptionTraceHolder::~ExceptionTraceHolder() {}
54*65c59e02SInna Palant 
ExceptionTraceHolder()55*65c59e02SInna Palant detail::ExceptionTraceHolder::ExceptionTraceHolder() {
56*65c59e02SInna Palant   // TODO(cjhopman): This should be done more safely (i.e. use preallocated
57*65c59e02SInna Palant   // space, etc.).
58*65c59e02SInna Palant   stackTrace_.reserve(128);
59*65c59e02SInna Palant   getStackTrace(stackTrace_, 1);
60*65c59e02SInna Palant }
61*65c59e02SInna Palant 
ensureRegisteredTerminateHandler()62*65c59e02SInna Palant void ensureRegisteredTerminateHandler() {
63*65c59e02SInna Palant   static auto initializer =
64*65c59e02SInna Palant       (gTerminateHandler = std::set_terminate(logExceptionAndAbort));
65*65c59e02SInna Palant   (void)initializer;
66*65c59e02SInna Palant }
67*65c59e02SInna Palant 
getExceptionTrace(std::exception_ptr ptr)68*65c59e02SInna Palant const std::vector<InstructionPointer>& getExceptionTrace(
69*65c59e02SInna Palant     std::exception_ptr ptr) {
70*65c59e02SInna Palant   static const std::vector<InstructionPointer> emptyTrace;
71*65c59e02SInna Palant #ifndef _WIN32
72*65c59e02SInna Palant   auto holder = getExceptionTraceHolder(ptr);
73*65c59e02SInna Palant   return holder ? holder->stackTrace_ : emptyTrace;
74*65c59e02SInna Palant #else
75*65c59e02SInna Palant   return emptyTrace;
76*65c59e02SInna Palant #endif
77*65c59e02SInna Palant }
78*65c59e02SInna Palant 
toString(std::exception_ptr ptr)79*65c59e02SInna Palant std::string toString(std::exception_ptr ptr) {
80*65c59e02SInna Palant   if (!ptr) {
81*65c59e02SInna Palant     return "No exception";
82*65c59e02SInna Palant   }
83*65c59e02SInna Palant 
84*65c59e02SInna Palant   try {
85*65c59e02SInna Palant     std::rethrow_exception(ptr);
86*65c59e02SInna Palant   } catch (std::exception& e) {
87*65c59e02SInna Palant     std::stringstream ss;
88*65c59e02SInna Palant     ss << typeid(e).name() << ": " << e.what();
89*65c59e02SInna Palant     return ss.str();
90*65c59e02SInna Palant   } catch (...) {
91*65c59e02SInna Palant     return "Unknown exception";
92*65c59e02SInna Palant   }
93*65c59e02SInna Palant }
94*65c59e02SInna Palant 
95*65c59e02SInna Palant } // namespace lyra
96*65c59e02SInna Palant } // namespace facebook
97