inLimbo
TUI Music Player that keeps you in Limbo.
 
Loading...
Searching...
No Matches
signalHandler.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <climits> // For PATH_MAX
4#include <csignal>
5#include <cstdlib>
6#include <ctime> // For timestamps
7#include <execinfo.h>
8#include <fstream>
9#include <iostream>
10#include <pthread.h> // For thread info
11#include <string>
12#include <sys/resource.h> // For resource usage
13#include <sys/utsname.h> // For system info
14#include <unistd.h>
15#include <unistd.h> // For getpid, getppid
16
17class SignalHandler
18{
19public:
20 // Singleton instance getter
21 static auto getInstance() -> SignalHandler&
22 {
23 static SignalHandler instance;
24 return instance;
25 }
26
27 // Initialize the signal handler
28 void setup()
29 {
30 struct sigaction sa;
31 sa.sa_sigaction = SignalHandler::handleSignal; // Use static member function
32 sigemptyset(&sa.sa_mask);
33 sa.sa_flags = SA_SIGINFO; // Use siginfo_t for extended info
34
35 sigaction(SIGABRT, &sa, nullptr); // Catch SIGABRT
36 sigaction(SIGSEGV, &sa, nullptr); // Catch SIGSEGV
37 }
38
39private:
40 SignalHandler() = default; // Private constructor for singleton
41 ~SignalHandler() = default;
42
43 // Non-copyable and non-movable
44 SignalHandler(const SignalHandler&) = delete;
45 auto operator=(const SignalHandler&) -> SignalHandler& = delete;
46
47 // Get current timestamp as a string
48 static auto getCurrentTimestamp() -> std::string
49 {
50 std::time_t now = std::time(nullptr);
51 char buffer[100];
52 std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", std::localtime(&now));
53 return std::string(buffer);
54 }
55
56 static void createCacheDirectory(const std::string& path)
57 {
58 struct stat info;
59 if (stat(path.c_str(), &info) != 0 || !(info.st_mode & S_IFDIR))
60 {
61 mkdir(path.c_str(), 0755); // Create directory with rwx permissions
62 }
63 }
64
65 // Get system and environment details
66 static void logSystemInfo(std::ofstream& logFile)
67 {
68 // Process and thread information
69 logFile << "Process ID: " << getpid() << "\n";
70 logFile << "Parent Process ID: " << getppid() << "\n";
71 logFile << "Thread ID: " << pthread_self() << "\n";
72
73 // Current working directory
74 char cwd[PATH_MAX];
75 if (getcwd(cwd, sizeof(cwd)))
76 {
77 logFile << "Current Working Directory: " << cwd << "\n";
78 }
79
80 // System information
81 struct utsname sysInfo;
82 if (uname(&sysInfo) == 0)
83 {
84 logFile << "System Name: " << sysInfo.sysname << "\n";
85 logFile << "Node Name: " << sysInfo.nodename << "\n";
86 logFile << "Release: " << sysInfo.release << "\n";
87 logFile << "Version: " << sysInfo.version << "\n";
88 logFile << "Machine: " << sysInfo.machine << "\n";
89 }
90
91 // Resource usage
92 struct rusage usage;
93 if (getrusage(RUSAGE_SELF, &usage) == 0)
94 {
95 logFile << "CPU Time Used (user): " << usage.ru_utime.tv_sec << "s " << usage.ru_utime.tv_usec
96 << "us\n";
97 logFile << "CPU Time Used (system): " << usage.ru_stime.tv_sec << "s "
98 << usage.ru_stime.tv_usec << "us\n";
99 logFile << "Max Resident Set Size: " << usage.ru_maxrss << " KB\n";
100 }
101 }
102
103 // Signal handling function
104 static void handleSignal(int signal, siginfo_t* info, void* context)
105 {
106 const char* signalName = nullptr;
107 switch (signal)
108 {
109 case SIGABRT:
110 signalName = "SIGABRT";
111 break;
112 case SIGSEGV:
113 signalName = "SIGSEGV";
114 break;
115 default:
116 signalName = "Unknown";
117 break;
118 }
119
120 std::string logDir = std::string(std::getenv("HOME")) + "/.cache/inLimbo/";
121 createCacheDirectory(logDir); // Ensure the directory exists
122
123 std::string logFileName = logDir + "debug-" + std::to_string(signal) + ".log";
124 std::ofstream logFile(logFileName, std::ios::out | std::ios::app);
125
126 if (logFile.is_open())
127 {
128 logFile << "=== Signal Caught ===\n";
129 logFile << "Timestamp: " << getCurrentTimestamp() << "\n";
130 logFile << "Signal: " << signalName << " (" << signal << ")\n";
131 if (info)
132 {
133 logFile << "Address causing signal: " << info->si_addr << "\n";
134 }
135
136 // Log system and environment information
137 logSystemInfo(logFile);
138
139 // Generate a backtrace
140 void* buffer[128];
141 int size = backtrace(buffer, 128);
142 logFile << "Backtrace (" << size << " frames):\n";
143 char** symbols = backtrace_symbols(buffer, size);
144 for (int i = 0; i < size; ++i)
145 {
146 logFile << symbols[i] << '\n';
147 }
148 free(symbols);
149
150 logFile.close();
151
152 std::cerr << "** Critical error occurred. See " << logFileName << " for details.**\n"
153 << "Exiting..." << std::endl;
154 }
155 else
156 {
157 std::cerr << "-- Failed to write to log file: " << logFileName << "\n";
158 }
159
160 // Clean termination
161 _Exit(EXIT_FAILURE);
162 }
163};
Definition signalHandler.hpp:18
static auto getInstance() -> SignalHandler &
Definition signalHandler.hpp:21
void setup()
Definition signalHandler.hpp:28