Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAndroidCrashHandler Namespace Reference

Functions

void crash_callback (int sig, siginfo_t *info, void *ucontext)
 
void dump_backtrace (siginfo_t *info, void *ucontext)
 
const char * get_signal_name (const int signo)
 
void handler_init ()
 

Variables

static const char * crashlog_path = path.c_str()
 
static bool g_handling_crash = false
 
static QMap< int, struct sigaction > g_old_actions
 
static const std::string path
 
static const std::array< int, 6 > signals = {SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGSYS, SIGTERM}
 

Function Documentation

◆ crash_callback()

void KisAndroidCrashHandler::crash_callback ( int sig,
siginfo_t * info,
void * ucontext )

Definition at line 102 of file KisAndroidCrashHandler.cpp.

103{
104 // to prevent second invocation of our signal handler
105 if (g_handling_crash) {
106 // uninstall the handler for the signal
107 sigaction(sig, &g_old_actions[sig], nullptr);
108 raise(sig);
109 return;
110 }
111
112 g_handling_crash = true;
113 dump_backtrace(info, ucontext);
114
115 // uninstall the handler for the signal
116 sigaction(sig, &g_old_actions[sig], nullptr);
117
118 // invoke the previous handler
119 // Some other implementations tend to make call to handler functions
120 // directly, seemingly to not make another _slow_ syscall.
121 raise(sig);
122}

References dump_backtrace(), g_handling_crash, and g_old_actions.

◆ dump_backtrace()

void KisAndroidCrashHandler::dump_backtrace ( siginfo_t * info,
void * ucontext )

Definition at line 60 of file KisAndroidCrashHandler.cpp.

61{
62 QScopedPointer<unwindstack::Regs> regs;
63 if (ucontext) {
64 regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
65 } else {
66 regs.reset(unwindstack::Regs::CreateFromLocal());
67 }
68
69 unwindstack::UnwinderFromPid unwinder(256, getpid(), unwindstack::Regs::CurrentArch());
70 if (!unwinder.Init()) {
71 CRASH_LOGGER("Couldn't initialize the unwinder: %s\n", unwinder.LastErrorCodeString());
72 return;
73 }
74
75 unwinder.SetRegs(regs.data());
76 unwinder.Unwind();
77
78 std::vector<unwindstack::FrameData> frames = unwinder.frames();
79 if (frames.size() == 0) {
80 CRASH_LOGGER("Couldn't unwind: %s\t code = %d\n", unwinder.LastErrorCodeString(), unwinder.LastErrorCode());
81 return;
82 }
83
84 const int fd = open(crashlog_path, O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR);
85
86 std::stringstream header;
87 header << "********************** Dumping backtrace **********************\n"
88 << "Signal: " << info->si_signo << " (" << get_signal_name(info->si_signo) << ")"
89 << " (Code: " << info->si_code << ")"
90 << " Time: " << QDateTime::currentDateTimeUtc().toString().toStdString().c_str()
91 << " Version: " << KritaVersionWrapper::versionString(true).toStdString().c_str() << "\n";
92 write(fd, header.str().c_str(), header.str().size());
93
94 for (size_t i = 0; i < frames.size(); ++i) {
95 std::string frame = unwinder.FormatFrame(frames[i]) + "\n";
96 write(fd, frame.c_str(), frame.size());
97 }
98 write(fd, "\n", 1);
99 close(fd);
100}
#define CRASH_LOGGER(...)
QAction * close(const QObject *recvr, const char *slot, QObject *parent)
QAction * open(const QObject *recvr, const char *slot, QObject *parent)
const char * get_signal_name(const int signo)
KRITAVERSION_EXPORT QString versionString(bool checkGit=false)

References CRASH_LOGGER, crashlog_path, get_signal_name(), and KritaVersionWrapper::versionString().

◆ get_signal_name()

const char * KisAndroidCrashHandler::get_signal_name ( const int signo)

Definition at line 40 of file KisAndroidCrashHandler.cpp.

41{
42 switch (signo) {
43 case SIGABRT:
44 return "SIGABRT";
45 case SIGBUS:
46 return "SIGBUS";
47 case SIGFPE:
48 return "SIGFPE";
49 case SIGSEGV:
50 return "SIGSEGV";
51 case SIGSYS:
52 return "SIGSYS";
53 case SIGTERM:
54 return "SIGTERM";
55 default:
56 return "?";
57 }
58}

◆ handler_init()

KRITAGLOBAL_EXPORT void KisAndroidCrashHandler::handler_init ( )

Definition at line 124 of file KisAndroidCrashHandler.cpp.

125{
126 // create an alternate stack to make sure we can handle overflows
127 stack_t alternate_stack;
128 alternate_stack.ss_flags = 0;
129 alternate_stack.ss_size = SIGSTKSZ;
130 if ((alternate_stack.ss_sp = malloc(SIGSTKSZ)) == nullptr) {
131 CRASH_LOGGER("Couldn't allocate memory for alternate stack");
132 return;
133 }
134
135 struct sigaction act = {};
136 act.sa_sigaction = crash_callback;
137 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
138 sigaltstack(&alternate_stack, nullptr);
139
140 for (size_t i = 0; i < signals.size(); ++i) {
141 sigaction(signals[i], &act, &g_old_actions[signals[i]]);
142 }
143}
static const std::array< int, 6 > signals
void crash_callback(int sig, siginfo_t *info, void *ucontext)

References crash_callback(), CRASH_LOGGER, g_old_actions, and signals.

Variable Documentation

◆ crashlog_path

const char* KisAndroidCrashHandler::crashlog_path = path.c_str()
static

Definition at line 36 of file KisAndroidCrashHandler.cpp.

◆ g_handling_crash

bool KisAndroidCrashHandler::g_handling_crash = false
static

Definition at line 38 of file KisAndroidCrashHandler.cpp.

◆ g_old_actions

QMap<int, struct sigaction> KisAndroidCrashHandler::g_old_actions
static

Definition at line 31 of file KisAndroidCrashHandler.cpp.

◆ path

const std::string KisAndroidCrashHandler::path
static
Initial value:
=
QString(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/kritacrashlog.txt").toStdString()

Definition at line 34 of file KisAndroidCrashHandler.cpp.

◆ signals

const std::array<int, 6> KisAndroidCrashHandler::signals = {SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGSYS, SIGTERM}
static

Definition at line 30 of file KisAndroidCrashHandler.cpp.

30{SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGSYS, SIGTERM};