//# Error2.cc: Base class for all Casacore errors (non-templated classes) //# Copyright (C) 1993,1994,1995,1996,1997,2000,2001 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #include #include #include #include #include //# needed for strerror_r //# Stacktracing requires some extra includes. #ifdef USE_STACKTRACE # include # include # include # define AddStackTrace() addStackTrace() #else # define AddStackTrace() #endif namespace casacore { //# NAMESPACE CASACORE - BEGIN AipsError::AipsError (Category c) : message(), category(c) { AddStackTrace(); } AipsError::AipsError(const Char *str,Category c) : message(str), category(c) { AddStackTrace(); } AipsError::AipsError(const String &str,Category c) : message(str), category(c) { AddStackTrace(); } AipsError::AipsError (const String &msg, const String& filename, uInt lineNumber, Category c) : category(c) { ostringstream os; os << msg << " at File: " << filename << ", line: " << lineNumber; message = os.str(); AddStackTrace (); } AipsError::~AipsError() noexcept {} #ifndef USE_STACKTRACE String AipsError::getStackTrace () const { return stackTrace; } void AipsError::addStackTrace() {} void AipsError::getLastInfo (String&, String&) {} String AipsError::getLastMessage () { return String(); } String AipsError::getLastStackTrace () { return String(); } void AipsError::clearLastInfo () {} #else // error message from last exception static String lastMessage = "*none*"; // stack trace from last exception static String lastStackTrace = "*no-stack-trace*"; // protects the lastMessage and lastStackTrace statics static std::mutex lastErrorMutex; void AipsError::getLastInfo (String & message, String & stackTrace) { std::lock_guard lock(lastErrorMutex); message = getLastMessage(); stackTrace = getLastStackTrace(); } String AipsError::getLastMessage () { return lastMessage; } String AipsError::getLastStackTrace () { return CasaErrorTools::replaceStackAddresses (lastStackTrace); } void AipsError::clearLastInfo () { std::lock_guard lock(lastErrorMutex); lastMessage = "*none*"; lastStackTrace = "*no-stack-trace*"; } void AipsError::addStackTrace() { // Always generate a stack trace and keep it around in a static // for later retrieval via casapy stackTrace = CasaErrorTools::generateStackTrace(); { std::lock_guard lock(lastErrorMutex); lastMessage = message; lastStackTrace = stackTrace; } // See if the default is to tack on the stack trace on the exception // message. N.B.: Turning this on will break some of the low-level tests // which simply compare expected to actual output. Bool enabled; AipsrcValue::find (enabled, "AipsError.enableStackTrace", False); if (enabled) { // If permitted, append to the error message. message += stackTrace; } } String AipsError::getStackTrace () const { return CasaErrorTools::replaceStackAddresses (stackTrace); } #endif void AipsError::throwIf (bool condition, const String& message, const char* file, Int line, const char* func) { // If the condition is met then throw an AipsError if (condition) { String m = String::format ("Exception: %s.\n... thrown by %s", message.c_str(), func); AipsError e (m.c_str(), file, line); throw e; } } void AipsError::throwIfError (int errorCode, const String& prefix, const char* file, Int line, const char* func) { // If the provided error code is not equal to success (0) then // throw an AipsError using the provided prefix and then details // of the error. if (errorCode != 0) { AipsError e (String::format ("Exception: %s.\n...Thrown by %s\n...(errno=%d): %s", prefix.c_str(), func, errorCode, strerror (errorCode)), file, line); throw e; } } AipsError AipsError::repackageAipsError (AipsError& error, const String& message, const char* file, Int line, const char* func) { ostringstream os; AipsError tmp (message, file, line); os << "+++Exception: " << tmp.getMesg() << ".\n...Thrown by " << func << ": " << "\n...Lower level exception: " << error.getMesg() << "\n--- end exception\n"; return AipsError (os.str()); } AllocError::~AllocError() noexcept {} IndexError::~IndexError() noexcept {} DuplError::~DuplError() noexcept {} SystemCallError::SystemCallError(const String& funcName, int error, Category c) : AipsError("Error in " + funcName + ": " + errorMessage(error), c), itsError (error) {} SystemCallError::SystemCallError (int error, const String &msg, const String &filename, uInt lineNumber, Category c) : AipsError (msg + String::format (": errno=%d: %s", error, errorMessage (error).c_str()), filename, lineNumber, c), itsError (error) {} SystemCallError::~SystemCallError() noexcept {} String strerror_overload(int err) { return "errno " + String::toString(err); } String strerror_overload(char *err) { return err; } String SystemCallError::errorMessage(int error) { // Use strerror_r for thread-safety. char buffer[128]; return strerror_overload(strerror_r(error, buffer, sizeof buffer)); } // Exception which causes an abort instead of continuing AbortError::AbortError(const Char *str,Category c) : AipsError(str,c) { cerr << "An unrecoverable error occurred: " << endl; cerr << str << endl; #ifndef CASACORE_NOEXIT exit(1); #endif } AbortError::AbortError(const String &str,Category c) : AipsError(str,c) { cerr << "An unrecoverable error occurred: " << endl; cerr << str << endl; #ifndef CASACORE_NOEXIT exit(1); #endif } AbortError::~AbortError() noexcept {} } //# NAMESPACE CASACORE - END