xref: /aosp_15_r20/external/fbjni/cxx/lyra/lyra_exceptions.cpp (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
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 <lyra/lyra_exceptions.h>
18 
19 #include <cstdlib>
20 #include <exception>
21 #include <sstream>
22 #include <typeinfo>
23 
24 #include <fbjni/detail/Log.h>
25 
26 namespace facebook {
27 namespace lyra {
28 
29 using namespace detail;
30 
31 namespace {
32 std::terminate_handler gTerminateHandler;
33 
logExceptionAndAbort()34 void logExceptionAndAbort() {
35   if (auto ptr = std::current_exception()) {
36     FBJNI_LOGE("Uncaught exception: %s", toString(ptr).c_str());
37 #ifndef _WIN32
38     auto trace = getExceptionTraceHolder(ptr);
39     if (trace) {
40       logStackTrace(getStackTraceSymbols(trace->stackTrace_));
41     }
42 #endif
43   }
44   if (gTerminateHandler) {
45     gTerminateHandler();
46   } else {
47     FBJNI_LOGF("Uncaught exception and no gTerminateHandler set");
48   }
49 }
50 
51 } // namespace
52 
~ExceptionTraceHolder()53 ExceptionTraceHolder::~ExceptionTraceHolder() {}
54 
ExceptionTraceHolder()55 detail::ExceptionTraceHolder::ExceptionTraceHolder() {
56   // TODO(cjhopman): This should be done more safely (i.e. use preallocated
57   // space, etc.).
58   stackTrace_.reserve(128);
59   getStackTrace(stackTrace_, 1);
60 }
61 
ensureRegisteredTerminateHandler()62 void ensureRegisteredTerminateHandler() {
63   static auto initializer =
64       (gTerminateHandler = std::set_terminate(logExceptionAndAbort));
65   (void)initializer;
66 }
67 
getExceptionTrace(std::exception_ptr ptr)68 const std::vector<InstructionPointer>& getExceptionTrace(
69     std::exception_ptr ptr) {
70   static const std::vector<InstructionPointer> emptyTrace;
71 #ifndef _WIN32
72   auto holder = getExceptionTraceHolder(ptr);
73   return holder ? holder->stackTrace_ : emptyTrace;
74 #else
75   return emptyTrace;
76 #endif
77 }
78 
toString(std::exception_ptr ptr)79 std::string toString(std::exception_ptr ptr) {
80   if (!ptr) {
81     return "No exception";
82   }
83 
84   try {
85     std::rethrow_exception(ptr);
86   } catch (std::exception& e) {
87     std::stringstream ss;
88     ss << typeid(e).name() << ": " << e.what();
89     return ss.str();
90   } catch (...) {
91     return "Unknown exception";
92   }
93 }
94 
95 } // namespace lyra
96 } // namespace facebook
97