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()34void 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()53ExceptionTraceHolder::~ExceptionTraceHolder() {} 54 ExceptionTraceHolder()55detail::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()62void ensureRegisteredTerminateHandler() { 63 static auto initializer = 64 (gTerminateHandler = std::set_terminate(logExceptionAndAbort)); 65 (void)initializer; 66 } 67 getExceptionTrace(std::exception_ptr ptr)68const 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)79std::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