Skip to content

Commit

Permalink
Use filename where exception was thrown in DumpStackBacktrace
Browse files Browse the repository at this point in the history
Allows us to turn on exceptions for specific files, rather that
filtering them all as Utils.cpp.

(cherry picked from commit 3590e97)
  • Loading branch information
qris committed Jul 23, 2017
1 parent 05f0e98 commit 67e9588
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 13 deletions.
2 changes: 1 addition & 1 deletion lib/common/Box.h
Expand Up @@ -31,7 +31,7 @@

#ifdef SHOW_BACKTRACE_ON_EXCEPTION
#include "Utils.h"
#define OPTIONAL_DO_BACKTRACE DumpStackBacktrace();
#define OPTIONAL_DO_BACKTRACE DumpStackBacktrace(__FILE__);
#else
#define OPTIONAL_DO_BACKTRACE
#endif
Expand Down
23 changes: 20 additions & 3 deletions lib/common/Logging.cpp
Expand Up @@ -284,12 +284,23 @@ bool Logging::ShouldLog(Log::Level default_level, Log::Level message_level,
const std::string& file, int line, const std::string& function, const Log::Category& category,
const std::string& message)
{
// Based on http://stackoverflow.com/a/40947954/648162 and
// http://stackoverflow.com/a/41367919/648162, but since we have to do this at runtime for
// each logging call, don't do the strrchr unless we have at least one override configured
// (otherwise it's never used, and a waste of CPU):
const char* current_file = NULL;
if(Logging::sLogLevelOverrideByFileGuards.begin() !=
Logging::sLogLevelOverrideByFileGuards.end())
{
current_file = strrchr(file.c_str(), DIRECTORY_SEPARATOR_ASCHAR) + 1;
}

Log::Level level_filter = default_level;
for(std::vector<LogLevelOverrideByFileGuard>::iterator
i = Logging::sLogLevelOverrideByFileGuards.begin();
i != Logging::sLogLevelOverrideByFileGuards.end(); i++)
{
if(i->IsOverridden(message_level, file, line, function, category, message))
if(i->IsOverridden(message_level, current_file, line, function, category, message))
{
level_filter = i->GetNewLevel();
}
Expand Down Expand Up @@ -745,9 +756,14 @@ int Logging::OptionParser::ProcessOption(signed int option)
// --------------------------------------------------------------------------
std::string Logging::OptionParser::GetUsageString()
{
return
// Based on http://stackoverflow.com/a/40947954/648162 and
// http://stackoverflow.com/a/41367919/648162:
const char* current_file = strrchr(__FILE__, DIRECTORY_SEPARATOR_ASCHAR) + 1;

std::ostringstream buf;
buf <<
" -L <file>=<level> Override log level for specified file, can repeat\n"
" (for example, -L '" __FILE__ "=trace')\n"
" (for example, -L '" << current_file << "=trace')\n"
" -N Truncate log file at startup and on backup start\n"
" -P Show process ID (PID) in console output\n"
" -q Run more quietly, reduce verbosity level by one, can repeat\n"
Expand All @@ -758,6 +774,7 @@ std::string Logging::OptionParser::GetUsageString()
" -v Run more verbosely, increase verbosity level by one, can repeat\n"
" -V Run at maximum verbosity, log everything to console and system\n"
" -W <level> Set verbosity to error/warning/notice/info/trace/everything\n";
return buf.str();
}

bool HideCategoryGuard::Log(Log::Level level, const std::string& file, int line,
Expand Down
2 changes: 1 addition & 1 deletion lib/common/Logging.h
Expand Up @@ -26,7 +26,7 @@
{ \
std::ostringstream _box_log_line; \
_box_log_line << stuff; \
Logging::Log(level, BOX_CURRENT_FILE, __LINE__, __FUNCTION__, \
Logging::Log(level, __FILE__, __LINE__, __FUNCTION__, \
Logging::UNCATEGORISED, _box_log_line.str()); \
}

Expand Down
29 changes: 23 additions & 6 deletions lib/common/Utils.cpp
Expand Up @@ -143,6 +143,12 @@ std::string RemoveSuffix(const std::string& suffix, const std::string& haystack)
}
}

// The backtrace routines are used by DebugMemLeakFinder, so we need to disable memory leak
// tracking during them, otherwise we could end up with infinite recursion.
#include "MemLeakFindOff.h"

const Log::Category BACKTRACE("Backtrace");

static std::string demangle(const std::string& mangled_name)
{
std::string demangled_name = mangled_name;
Expand Down Expand Up @@ -201,7 +207,7 @@ static std::string demangle(const std::string& mangled_name)
return demangled_name;
}

void DumpStackBacktrace()
void DumpStackBacktrace(const std::string& filename)
{
const int max_length = 20;
void *array[max_length];
Expand All @@ -216,11 +222,18 @@ void DumpStackBacktrace()
return;
#endif

BOX_TRACE("Obtained " << size << " stack frames.");
DumpStackBacktrace(size, array);
// Instead of calling BOX_TRACE, we call Logging::Log directly in order to pass filename
// as the source file. This allows exception backtraces to be turned on and off by file,
// instead of all of them originating in Utils.cpp.
std::ostringstream output;
output << "Obtained " << size << " stack frames.";
Logging::Log(Log::TRACE, filename, 0, // line
__FUNCTION__, BACKTRACE, output.str());

DumpStackBacktrace(filename, size, array);
}

void DumpStackBacktrace(size_t size, void * const * array)
void DumpStackBacktrace(const std::string& filename, size_t size, void * const * array)
{
#if defined WIN32
HANDLE hProcess = GetCurrentProcess();
Expand Down Expand Up @@ -277,7 +290,11 @@ void DumpStackBacktrace(size_t size, void * const * array)
(void *)diff;
}

BOX_TRACE(output.str());
// Instead of calling BOX_TRACE, we call Logging::Log directly in order to pass filename
// as the source file. This allows exception backtraces to be turned on and off by file,
// instead of all of them originating in Utils.cpp.
Logging::Log(Log::TRACE, filename, 0, // line
__FUNCTION__, BACKTRACE, output.str());
}
}

Expand Down Expand Up @@ -307,7 +324,7 @@ bool FileExists(const std::string& rFilename, int64_t *pFileSize,
}
}

// is it a file?
// is it a file?
if((st.st_mode & S_IFDIR) == 0)
{
if(TreatLinksAsNotExisting && ((st.st_mode & S_IFLNK) != 0))
Expand Down
3 changes: 2 additions & 1 deletion lib/common/Utils.h
Expand Up @@ -23,7 +23,8 @@ bool EndsWith(const std::string& prefix, const std::string& haystack);
std::string RemovePrefix(const std::string& prefix, const std::string& haystack);
std::string RemoveSuffix(const std::string& suffix, const std::string& haystack);

void DumpStackBacktrace();
void DumpStackBacktrace(const std::string& filename);
void DumpStackBacktrace(const std::string& filename, size_t size, void * const * array);

bool FileExists(const std::string& rFilename, int64_t *pFileSize = 0,
bool TreatLinksAsNotExisting = false);
Expand Down
2 changes: 1 addition & 1 deletion lib/server/SocketStream.cpp
Expand Up @@ -566,6 +566,6 @@ void SocketStream::CheckForMissingTimeout(int Timeout)
if (Timeout == IOStream::TimeOutInfinite)
{
BOX_WARNING("Network operation started with no timeout!");
DumpStackBacktrace();
OPTIONAL_DO_BACKTRACE;
}
}

0 comments on commit 67e9588

Please sign in to comment.