Skip to content

Commit

Permalink
ignore SIGPIPE and log all threads callstacks on crash
Browse files Browse the repository at this point in the history
  • Loading branch information
d99kris committed Mar 14, 2020
1 parent ad2c50e commit f83ac26
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 15 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Project
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project(nmail VERSION "1.52" LANGUAGES CXX)
project(nmail VERSION "1.53" LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)

# Ccache
Expand Down
5 changes: 5 additions & 0 deletions src/imapmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <vector>

#include "loghelp.h"
#include "util.h"

ImapManager::ImapManager(const std::string& p_User, const std::string& p_Pass,
const std::string& p_Host, const uint16_t p_Port,
Expand Down Expand Up @@ -229,6 +230,8 @@ bool ImapManager::ProcessIdle()

void ImapManager::Process()
{
THREAD_REGISTER();

if (m_Connect)
{
if (m_Imap.Login())
Expand Down Expand Up @@ -404,6 +407,8 @@ void ImapManager::Process()

void ImapManager::CacheProcess()
{
THREAD_REGISTER();

LOG_DEBUG("entering cache loop");
while (m_CacheRunning)
{
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ int main(int argc, char* argv[])
const std::string& logPath = Util::GetApplicationDir() + std::string("log.txt");
Log::SetPath(logPath);

THREAD_REGISTER();
Util::RegisterSignalHandler();

const std::string version = Util::GetAppVersion();
Expand Down
2 changes: 1 addition & 1 deletion src/nmail.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 1.47.8.
.TH NMAIL "1" "March 2020" "nmail v1.52" "User Commands"
.TH NMAIL "1" "March 2020" "nmail v1.53" "User Commands"
.SH NAME
nmail \- ncurses mail
.SH SYNOPSIS
Expand Down
2 changes: 2 additions & 0 deletions src/smtpmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ std::string SmtpManager::GetAddress()

void SmtpManager::Process()
{
THREAD_REGISTER();

LOG_DEBUG("entering loop");
while (m_Running)
{
Expand Down
73 changes: 60 additions & 13 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "util.h"

#include <algorithm>
#include <csignal>
#include <map>
#include <set>

Expand All @@ -34,6 +35,9 @@
#include "loghelp.h"
#include "serialized.h"

std::mutex ThreadRegister::m_Mutex;
std::map<pthread_t, std::string> ThreadRegister::m_Threads;

std::string Util::m_HtmlConvertCmd;
std::string Util::m_ExtViewerCmd;
std::string Util::m_ApplicationDir;
Expand Down Expand Up @@ -889,29 +893,72 @@ std::string Util::GetCompiler()
#endif
}

std::string Util::GetSigName(int p_Signal)
{
static std::map<int, std::string> signames =
{
{ SIGABRT, "SIGABRT" },
{ SIGSEGV, "SIGSEGV" },
{ SIGBUS, "SIGBUS" },
{ SIGILL, "SIGILL" },
{ SIGFPE, "SIGFPE" },
{ SIGTRAP, "SIGTRAP" },
{ SIGUSR1, "SIGUSR1" },
};

auto it = signames.find(p_Signal);
return (it != signames.end()) ? it->second : std::to_string(p_Signal);
}

void Util::RegisterSignalHandler()
{
signal(SIGABRT, SignalHandler);
signal(SIGSEGV, SignalHandler);
signal(SIGBUS, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGFPE, SignalHandler);
signal(SIGPIPE, SignalHandler);
signal(SIGBUS, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGFPE, SignalHandler);
signal(SIGTRAP, SignalHandler);
signal(SIGUSR1, SignalHandler);
}

static std::mutex s_SignalMutex;

void Util::SignalHandler(int p_Signal)
{
const std::string& threadLabel = "\nthread " + ThreadRegister::GetName() + "\n";
void *callstack[64];
int size = backtrace(callstack, sizeof(callstack));
const std::string& callstackStr = "\n" + BacktraceSymbolsStr(callstack, size) + "\n";
const std::string& logMsg = "unexpected termination: " + std::to_string(p_Signal);
LOG_ERROR("%s", logMsg.c_str());
LOG_DUMP(callstackStr.c_str());

CleanupStdErrRedirect();
system("reset");
std::cerr << logMsg << "\n" << callstackStr;
exit(1);
const std::string& callstackStr = BacktraceSymbolsStr(callstack, size);

if (p_Signal != SIGUSR1)
{
{
std::lock_guard<std::mutex> lock(s_SignalMutex);

const std::string& logMsg = "unexpected termination: " + GetSigName(p_Signal);
LOG_ERROR("%s", logMsg.c_str());
LOG_DUMP(threadLabel.c_str());
LOG_DUMP(callstackStr.c_str());

CleanupStdErrRedirect();
system("reset");
std::cerr << logMsg << "\n" << callstackStr << "\n";
}

if (Log::GetDebugEnabled())
{
ThreadRegister::SignalThreads(SIGUSR1);
sleep(1);
}

exit(1);
}
else
{
std::lock_guard<std::mutex> lock(s_SignalMutex);
LOG_DUMP(threadLabel.c_str());
LOG_DUMP(callstackStr.c_str());
}
}

std::string Util::BacktraceSymbolsStr(void* p_Callstack[], int p_Size)
Expand Down
45 changes: 45 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

#pragma once

#include <csignal>
#include <map>
#include <mutex>
#include <set>
#include <string>
#include <vector>
Expand All @@ -16,6 +19,8 @@
#define KEY_SPACE 32
#define KEY_DELETE 127

#define THREAD_REGISTER() ThreadRegister threadRegister(__PRETTY_FUNCTION__)

struct Fileinfo
{
Fileinfo()
Expand Down Expand Up @@ -63,6 +68,45 @@ struct FileinfoCompare
}
};

class ThreadRegister
{
public:
ThreadRegister(const std::string& p_Name)
{
std::lock_guard<std::mutex> lock(m_Mutex);
m_Threads.insert({ pthread_self(), p_Name });
}

~ThreadRegister()
{
std::lock_guard<std::mutex> lock(m_Mutex);
m_Threads.erase(pthread_self());
}

static std::string GetName()
{
std::lock_guard<std::mutex> lock(m_Mutex);
auto it = m_Threads.find(pthread_self());
return (it != m_Threads.end()) ? it->second : "";
}

static void SignalThreads(int p_Sig)
{
pthread_t self = pthread_self();
for (auto it = m_Threads.begin(); it != m_Threads.end(); ++it)
{
if (it->first != self)
{
pthread_kill(it->first, p_Sig);
}
}
}

private:
static std::mutex m_Mutex;
static std::map<pthread_t, std::string> m_Threads;
};

class Util
{
public:
Expand Down Expand Up @@ -161,6 +205,7 @@ class Util
static std::string GetSelfPath();
static std::string GetLibetpanVersion();
static std::string GetUname();
static std::string GetSigName(int p_Signal);

private:
static std::string m_HtmlConvertCmd;
Expand Down

0 comments on commit f83ac26

Please sign in to comment.