Skip to content

Commit

Permalink
add signal handler with crash logging
Browse files Browse the repository at this point in the history
  • Loading branch information
d99kris committed Jan 7, 2024
1 parent 78bc4cd commit 85b407a
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 8 deletions.
2 changes: 1 addition & 1 deletion lib/common/src/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

#pragma once

#define NCHAT_VERSION "4.26"
#define NCHAT_VERSION "4.27"
43 changes: 42 additions & 1 deletion lib/ncutil/src/apputil.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
// apputil.cpp
//
// Copyright (c) 2020-2023 Kristofer Berggren
// Copyright (c) 2020-2024 Kristofer Berggren
// All rights reserved.
//
// nchat is distributed under the MIT license, see LICENSE for details.

#include "apputil.h"

#include <set>

#include <execinfo.h>
#include <signal.h>
#include <unistd.h>

#include <sys/resource.h>
Expand Down Expand Up @@ -69,3 +73,40 @@ void AppUtil::InitCoredump()
}
#endif
}

void AppUtil::InitSignalHandler()
{
static const std::set<int> signals =
{
SIGABRT,
SIGBUS,
SIGFPE,
SIGILL,
SIGQUIT,
SIGSEGV,
SIGSYS,
SIGTRAP,
};

for (const auto sig : signals)
{
signal(sig, SignalHandler);
}
}

void AppUtil::SignalHandler(int p_Signal)
{
char logMsg[64];
snprintf(logMsg, sizeof(logMsg), "Unexpected termination %d\nCallstack:\n", p_Signal);
void* callstack[64] = { 0 };
const int size = backtrace(callstack, sizeof(callstack));
Log::Callstack(callstack, size, logMsg);

// non-signal safe code section
system("reset");
write(STDERR_FILENO, logMsg, strlen(logMsg));
backtrace_symbols_fd(callstack, size, STDERR_FILENO);

signal(p_Signal, SIG_DFL);
kill(getpid(), p_Signal);
}
4 changes: 3 additions & 1 deletion lib/ncutil/src/apputil.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// apputil.h
//
// Copyright (c) 2020-2023 Kristofer Berggren
// Copyright (c) 2020-2024 Kristofer Berggren
// All rights reserved.
//
// nchat is distributed under the MIT license, see LICENSE for details.
Expand All @@ -17,6 +17,8 @@ class AppUtil
static void SetDeveloperMode(bool p_DeveloperMode);
static bool GetDeveloperMode();
static void InitCoredump();
static void InitSignalHandler();
static void SignalHandler(int p_Signal);

private:
static bool m_DeveloperMode;
Expand Down
29 changes: 27 additions & 2 deletions lib/ncutil/src/log.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
// log.cpp
//
// Copyright (c) 2020-2023 Kristofer Berggren
// Copyright (c) 2020-2024 Kristofer Berggren
// All rights reserved.
//
// nchat is distributed under the MIT license, see LICENSE for details.

#include "log.h"

#include <execinfo.h>
#include <fcntl.h>
#include <stdarg.h>
#include <unistd.h>

#include <sys/time.h>

std::string Log::m_Path;
int Log::m_VerboseLevel = 0;
std::mutex Log::m_Mutex;
int Log::m_LogFd = -1;

void Log::Init(const std::string& p_Path)
{
m_Path = p_Path;
const std::string archivePath = m_Path + ".1";
remove(archivePath.c_str());
rename(m_Path.c_str(), archivePath.c_str());
Dump("");
m_LogFd = open(m_Path.c_str(), O_WRONLY | O_APPEND);
}

void Log::Cleanup()
{
if (m_LogFd != -1)
{
close(m_LogFd);
}
}

void Log::SetVerboseLevel(int p_Level)
Expand Down Expand Up @@ -86,7 +101,17 @@ void Log::Dump(const char* p_Str)
}
}

void Log::Write(const char* p_Filename, int p_LineNo, const char* p_Level, const char* p_Format, va_list p_VaList)
void Log::Callstack(void* const* p_Callstack, int p_Size, const char* p_LogMsg)
{
if (m_LogFd != -1)
{
write(m_LogFd, p_LogMsg, strlen(p_LogMsg));
backtrace_symbols_fd(p_Callstack, p_Size, m_LogFd);
}
}

void Log::Write(const char* p_Filename, int p_LineNo, const char* p_Level,
const char* p_Format, va_list p_VaList)
{
std::unique_lock<std::mutex> lock(m_Mutex);
if (m_Path.empty()) return;
Expand Down
8 changes: 6 additions & 2 deletions lib/ncutil/src/log.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// log.h
//
// Copyright (c) 2020-2023 Kristofer Berggren
// Copyright (c) 2020-2024 Kristofer Berggren
// All rights reserved.
//
// nchat is distributed under the MIT license, see LICENSE for details.
Expand All @@ -27,6 +27,7 @@ class Log
static const int TRACE_LEVEL = 2;

static void Init(const std::string& p_Path);
static void Cleanup();
static void SetVerboseLevel(int p_Level);
static inline int GetVerboseLevel() { return m_VerboseLevel; }
static inline bool GetDebugEnabled() { return m_VerboseLevel >= DEBUG_LEVEL; }
Expand All @@ -39,12 +40,15 @@ class Log
static void Error(const char* p_Filename, int p_LineNo, const char* p_Format, ...);

static void Dump(const char* p_Str);
static void Callstack(void* const* p_Callstack, int p_Size, const char* p_LogMsg);

private:
static void Write(const char* p_Filename, int p_LineNo, const char* p_Level, const char* p_Format, va_list p_VaList);
static void Write(const char* p_Filename, int p_LineNo, const char* p_Level,
const char* p_Format, va_list p_VaList);

private:
static std::string m_Path;
static int m_VerboseLevel;
static std::mutex m_Mutex;
static int m_LogFd;
};
5 changes: 5 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ int main(int argc, char* argv[])
std::string appNameVersion = AppUtil::GetAppNameVersion();
LOG_INFO("starting %s", appNameVersion.c_str());

// Init signal handler
AppUtil::InitSignalHandler();

// Run keydump if required
if (isKeyDump)
{
Expand Down Expand Up @@ -389,6 +392,8 @@ int main(int argc, char* argv[])

LOG_INFO("exiting nchat");

Log::Cleanup();

return rv;
}

Expand Down
2 changes: 1 addition & 1 deletion src/nchat.1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH NCHAT "1" "January 2024" "nchat v4.26" "User Commands"
.TH NCHAT "1" "January 2024" "nchat v4.27" "User Commands"
.SH NAME
nchat \- ncurses chat
.SH SYNOPSIS
Expand Down

0 comments on commit 85b407a

Please sign in to comment.