Skip to content

Commit

Permalink
Skip irrelevant frames in stacktraces (#1934)
Browse files Browse the repository at this point in the history
* Skip irrelevant frames in stacktraces

* Add optional startlevel for stacktrace
* Fix maxLevel, which should be interpreted relative to the startlevel
  • Loading branch information
dweindl authored Jan 16, 2023
1 parent 0d371d8 commit 8c58eb3
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 76 deletions.
6 changes: 4 additions & 2 deletions include/amici/exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ class AmiException : public std::exception {
public:
/**
* @brief Default ctor.
* @param first_frame Index of first frame to include
*/
AmiException();
AmiException(int const first_frame = 3);

/**
* @brief Constructor with printf style interface
Expand All @@ -43,8 +44,9 @@ class AmiException : public std::exception {
/**
* @brief Stores the current backtrace
* @param nMaxFrames number of frames to go back in stacktrace
* @param first_frame Index of first frame to include
*/
void storeBacktrace(int nMaxFrames);
void storeBacktrace(int nMaxFrames, int const first_frame);

protected:
/**
Expand Down
54 changes: 26 additions & 28 deletions include/amici/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ gsl::span<T> slice(std::vector<T> &data, int index, unsigned size) {
*/

template <class T>
gsl::span<const T> slice(const std::vector<T> &data,
int index, unsigned size) {
gsl::span<T const> slice(std::vector<T> const& data, int index, unsigned size) {
if ((index + 1) * size > data.size())
throw std::out_of_range("requested slice is out of data range");
if (size > 0)
Expand Down Expand Up @@ -78,7 +77,7 @@ void checkBufferSize(gsl::span<T> buffer,
* @param buffer buffer to which values are to be written
*/
template <class T>
void writeSlice(const gsl::span<const T> slice, gsl::span<T> buffer) {
void writeSlice(const gsl::span<T const> slice, gsl::span<T> buffer) {
checkBufferSize(buffer, slice.size());
std::copy(slice.begin(), slice.end(), buffer.data());
};
Expand All @@ -89,7 +88,7 @@ void writeSlice(const gsl::span<const T> slice, gsl::span<T> buffer) {
* @param buffer buffer to which values are to be added
*/
template <class T>
void addSlice(const gsl::span<const T> slice, gsl::span<T> buffer) {
void addSlice(const gsl::span<T const> slice, gsl::span<T> buffer) {
checkBufferSize(buffer, slice.size());
std::transform(slice.begin(), slice.end(), buffer.begin(), buffer.begin(),
std::plus<T>());
Expand All @@ -100,8 +99,7 @@ void addSlice(const gsl::span<const T> slice, gsl::span<T> buffer) {
* @param s computed value
* @param b buffer to which values are to be written
*/
template <class T>
void writeSlice(const std::vector<T> &s, std::vector<T> &b) {
template <class T> void writeSlice(std::vector<T> const& s, std::vector<T>& b) {
writeSlice(gsl::make_span(s.data(), s.size()),
gsl::make_span(b.data(), b.size()));
};
Expand All @@ -111,8 +109,7 @@ void writeSlice(const std::vector<T> &s, std::vector<T> &b) {
* @param s computed value
* @param b buffer to which values are to be written
*/
template <class T>
void writeSlice(const std::vector<T> &s, gsl::span<T> b) {
template <class T> void writeSlice(std::vector<T> const& s, gsl::span<T> b) {
writeSlice(gsl::make_span(s.data(), s.size()), b);
};

Expand All @@ -121,8 +118,7 @@ void writeSlice(const std::vector<T> &s, gsl::span<T> b) {
* @param s computed value
* @param b buffer to which values are to be written
*/
template <class T>
void addSlice(const std::vector<T> &s, gsl::span<T> b) {
template <class T> void addSlice(std::vector<T> const& s, gsl::span<T> b) {
addSlice(gsl::make_span(s.data(), s.size()), b);
};

Expand All @@ -131,21 +127,21 @@ void addSlice(const std::vector<T> &s, gsl::span<T> b) {
* @param s computed value
* @param b buffer to which values are to be written
*/
void writeSlice(const AmiVector &s, gsl::span<realtype> b);

void writeSlice(AmiVector const& s, gsl::span<realtype> b);

/**
* @brief Remove parameter scaling according to the parameter scaling in pscale
*
* All vectors must be of same length.
*
* @param bufferScaled scaled parameters
* @param pscale parameter scaling
* @param bufferUnscaled unscaled parameters are written to the array
*/
void unscaleParameters(gsl::span<const realtype> bufferScaled,
gsl::span<const ParameterScaling> pscale,
gsl::span<realtype> bufferUnscaled);
* @brief Remove parameter scaling according to the parameter scaling in pscale
*
* All vectors must be of same length.
*
* @param bufferScaled scaled parameters
* @param pscale parameter scaling
* @param bufferUnscaled unscaled parameters are written to the array
*/
void unscaleParameters(
gsl::span<realtype const> bufferScaled,
gsl::span<ParameterScaling const> pscale, gsl::span<realtype> bufferUnscaled
);

/**
* @brief Remove parameter scaling according to `scaling`
Expand Down Expand Up @@ -173,16 +169,18 @@ double getScaledParameter(double unscaledParameter, ParameterScaling scaling);
* @param pscale parameter scaling
* @param bufferScaled destination
*/
void scaleParameters(gsl::span<const realtype> bufferUnscaled,
gsl::span<const ParameterScaling> pscale,
gsl::span<realtype> bufferScaled);
void scaleParameters(
gsl::span<realtype const> bufferUnscaled,
gsl::span<ParameterScaling const> pscale, gsl::span<realtype> bufferScaled
);

/**
* @brief Returns the current backtrace as std::string
* @param maxFrames Number of frames to include
* @param first_frame Index of first frame to include
* @return Backtrace
*/
std::string backtraceString(int maxFrames);
std::string backtraceString(int maxFrames, int const first_frame = 0);

/**
* @brief Convert std::regex_constants::error_type to string
Expand All @@ -197,7 +195,7 @@ std::string regexErrorToString(std::regex_constants::error_type err_type);
* @param ap Argument list pointer
* @return Formatted String
*/
std::string printfToString(const char *fmt, va_list ap);
std::string printfToString(char const* fmt, va_list ap);

/**
* @brief Generic implementation for a context manager, explicitly deletes copy
Expand Down
50 changes: 25 additions & 25 deletions src/exception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,42 @@

namespace amici {

AmiException::AmiException()
{
storeBacktrace(12);
AmiException::AmiException(int const first_frame) {
storeBacktrace(12, first_frame);
}

AmiException::AmiException(const char *fmt, ...)
: AmiException()
{
AmiException::AmiException(char const* fmt, ...)
: AmiException(4) {
va_list ap;
va_start(ap, fmt);
storeMessage(fmt, ap);
va_end(ap);
}

const char *AmiException::what() const noexcept {
return msg_.data();
}
char const* AmiException::what() const noexcept { return msg_.data(); }

const char *AmiException::getBacktrace() const {
return trace_.data();
}
char const* AmiException::getBacktrace() const { return trace_.data(); }

void AmiException::storeBacktrace(const int nMaxFrames) {
snprintf(trace_.data(), trace_.size(), "%s",
backtraceString(nMaxFrames).c_str());
void AmiException::storeBacktrace(int const nMaxFrames, int const first_frame) {
snprintf(
trace_.data(), trace_.size(), "%s",
backtraceString(nMaxFrames, first_frame).c_str()
);
}

void AmiException::storeMessage(const char *fmt, va_list argptr)
{
void AmiException::storeMessage(char const* fmt, va_list argptr) {
vsnprintf(msg_.data(), msg_.size(), fmt, argptr);
}

CvodeException::CvodeException(const int error_code, const char *function) :
AmiException("Cvode routine %s failed with error code %i",function,error_code){}
CvodeException::CvodeException(int const error_code, char const* function)
: AmiException(
"Cvode routine %s failed with error code %i", function, error_code
) {}

IDAException::IDAException(const int error_code, const char *function) :
AmiException("IDA routine %s failed with error code %i",function,error_code){}
IDAException::IDAException(int const error_code, char const* function)
: AmiException(
"IDA routine %s failed with error code %i", function, error_code
) {}

IntegrationFailure::IntegrationFailure(int code, realtype t) :
AmiException("AMICI failed to integrate the forward problem"),
Expand All @@ -54,13 +53,14 @@ IntegrationFailureB::IntegrationFailureB(int code, realtype t) :
AmiException("AMICI failed to integrate the backward problem"),
error_code(code), time(t) {}

NewtonFailure::NewtonFailure(int code, const char *function) :
AmiException("NewtonSolver routine %s failed with error code %i",function,code) {
NewtonFailure::NewtonFailure(int code, char const* function)
: AmiException(
"NewtonSolver routine %s failed with error code %i", function, code
) {
error_code = code;
}

SetupFailure::SetupFailure(const char *fmt, ...)
{
SetupFailure::SetupFailure(char const* fmt, ...) {
va_list ap;
va_start(ap, fmt);
storeMessage(fmt, ap);
Expand Down
38 changes: 17 additions & 21 deletions src/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

namespace amici {

void writeSlice(const AmiVector &s, gsl::span<realtype> b) {
void writeSlice(AmiVector const& s, gsl::span<realtype> b) {
writeSlice(s.getVector(), b);
};

Expand All @@ -38,10 +38,10 @@ double getUnscaledParameter(double scaledParameter, ParameterScaling scaling)
throw AmiException("Invalid value for ParameterScaling.");
}

void unscaleParameters(gsl::span<const realtype> bufferScaled,
gsl::span<const ParameterScaling> pscale,
gsl::span<realtype> bufferUnscaled)
{
void unscaleParameters(
gsl::span<realtype const> bufferScaled,
gsl::span<ParameterScaling const> pscale, gsl::span<realtype> bufferUnscaled
) {
Expects(bufferScaled.size() == pscale.size());
Expects(bufferScaled.size() == bufferUnscaled.size());

Expand All @@ -51,7 +51,6 @@ void unscaleParameters(gsl::span<const realtype> bufferScaled,
}
}


double getScaledParameter(double unscaledParameter, ParameterScaling scaling)
{
switch (scaling) {
Expand All @@ -66,35 +65,32 @@ double getScaledParameter(double unscaledParameter, ParameterScaling scaling)
throw AmiException("Invalid value for ParameterScaling.");
}


void scaleParameters(gsl::span<const realtype> bufferUnscaled,
gsl::span<const ParameterScaling> pscale,
gsl::span<realtype> bufferScaled)
{
void scaleParameters(
gsl::span<realtype const> bufferUnscaled,
gsl::span<ParameterScaling const> pscale, gsl::span<realtype> bufferScaled
) {
Expects(bufferScaled.size() == pscale.size());
Expects(bufferScaled.size() == bufferUnscaled.size());

for (gsl::span<realtype>::index_type ip = 0;
ip < bufferUnscaled.size(); ++ip) {
bufferScaled[ip] = getScaledParameter(bufferUnscaled[ip], pscale[ip]);
}

}

std::string backtraceString(const int maxFrames)
{
std::string backtraceString(int const maxFrames, int const first_frame) {
std::ostringstream trace_buf;

#ifdef PLATFORM_WINDOWS
trace_buf << "stacktrace not available on windows platforms\n";
#else
void *callstack[maxFrames];
int const last_frame = first_frame + maxFrames;
void* callstack[last_frame];
char buf[1024];
int nFrames = backtrace(callstack, maxFrames);
int nFrames = backtrace(callstack, last_frame);
char **symbols = backtrace_symbols(callstack, nFrames);

// start at 2 to omit AmiException and storeBacktrace
for (int i = 2; i < nFrames; i++) {
for (int i = first_frame; i < nFrames; i++) {
// call
Dl_info info;
if (dladdr(callstack[i], &info) && info.dli_sname) {
Expand All @@ -120,8 +116,8 @@ std::string backtraceString(const int maxFrames)
}
free(symbols);

if (nFrames == maxFrames)
trace_buf << "[truncated]\n";
if (nFrames == last_frame)
trace_buf << "[possibly truncated]\n";
#endif
return trace_buf.str();
}
Expand Down Expand Up @@ -160,7 +156,7 @@ std::string regexErrorToString(std::regex_constants::error_type err_type)
}
}

std::string printfToString(const char *fmt, va_list ap) {
std::string printfToString(char const* fmt, va_list ap) {
// Get size of string
va_list ap_count;
va_copy(ap_count, ap);
Expand Down

0 comments on commit 8c58eb3

Please sign in to comment.