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 Palantvoid 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 PalantExceptionTraceHolder::~ExceptionTraceHolder() {} 54*65c59e02SInna Palant ExceptionTraceHolder()55*65c59e02SInna Palantdetail::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 Palantvoid 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 Palantconst 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 Palantstd::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