debug: print stack trace without crashing

This commit is contained in:
Lukas Oberhuber 2023-07-15 17:25:50 +01:00
parent 856fa41621
commit c1b4770c40
1 changed files with 60 additions and 17 deletions

View File

@ -27,6 +27,7 @@
#ifdef PLATFORM_OSX #ifdef PLATFORM_OSX
#include <AppKit/AppKit.h> #include <AppKit/AppKit.h>
#include <libunwind.h>
#endif #endif
#ifdef HAVE_EXECINFO_H #ifdef HAVE_EXECINFO_H
@ -1220,6 +1221,61 @@ gimp_stack_trace_print (const gchar *prog_name,
{ {
gboolean stack_printed = FALSE; gboolean stack_printed = FALSE;
#ifdef PLATFORM_OSX
pid_t pid = getpid();
uint64 tid64;
long tid;
GString *gtrace = NULL;
/* On macOS, we can't use gdb or lldb to attach to a process, so we
* have to use the stacktrace() API.
*/
unw_cursor_t cursor;
unw_context_t context;
unw_getcontext (&context);
unw_init_local (&cursor, &context);
pthread_threadid_np (NULL, &tid64);
tid = (long) tid64;
if (stream)
g_fprintf (stream,
"\n# Stack traces obtained from PID %d - Thread 0x%lx #\n\n",
pid, tid);
if (trace)
{
gtrace = g_string_new (NULL);
g_string_printf (gtrace,
"\n# Stack traces obtained from PID %d - Thread 0x%lx #\n\n",
pid, tid);
}
while (unw_step (&cursor) > 0)
{
unw_word_t offset, pc;
char fname[64];
unw_get_reg (&cursor, UNW_REG_IP, &pc);
fname[0] = '\0';
unw_get_proc_name (&cursor, fname, sizeof(fname), &offset);
stack_printed = TRUE;
if (stream)
g_fprintf (stream, "%p : (%s+0x%lx)\n", (void *)pc, fname, (unsigned long)offset);
if (trace)
g_string_append_printf (gtrace, "%p : (%s+0x%lx)\n", (void *) pc, fname, (unsigned long) offset);
}
if (trace)
*trace = g_string_free (gtrace, FALSE);
/* Stack printing conflicts with the OS stack printing */
return stack_printed;
#else /* PLATFORM_OSX */
/* This works only on UNIX systems. */ /* This works only on UNIX systems. */
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
GString *gtrace = NULL; GString *gtrace = NULL;
@ -1233,12 +1289,6 @@ gimp_stack_trace_print (const gchar *prog_name,
gint eintr_count = 0; gint eintr_count = 0;
#if defined(G_OS_WIN32) #if defined(G_OS_WIN32)
DWORD tid = GetCurrentThreadId (); DWORD tid = GetCurrentThreadId ();
#elif defined(PLATFORM_OSX)
uint64 tid64;
long tid;
pthread_threadid_np (NULL, &tid64);
tid = (long) tid64;
#elif defined(SYS_gettid) #elif defined(SYS_gettid)
long tid = syscall (SYS_gettid); long tid = syscall (SYS_gettid);
#elif defined(HAVE_THR_SELF) #elif defined(HAVE_THR_SELF)
@ -1351,6 +1401,7 @@ gimp_stack_trace_print (const gchar *prog_name,
* Yet to avoid infinite loop (in case the error really * Yet to avoid infinite loop (in case the error really
* happens at every call), we abandon after a few * happens at every call), we abandon after a few
* consecutive errors. * consecutive errors.
* Note: macOS no longer runs through this code path
*/ */
if (errno == EINTR && eintr_count <= 5) if (errno == EINTR && eintr_count <= 5)
{ {
@ -1362,12 +1413,7 @@ gimp_stack_trace_print (const gchar *prog_name,
eintr_count = 0; eintr_count = 0;
if (! stack_printed) if (! stack_printed)
{ {
#if defined(PLATFORM_OSX) #if defined(G_OS_WIN32) || defined(SYS_gettid) || defined(HAVE_THR_SELF)
if (stream)
g_fprintf (stream,
"\n# Stack traces obtained from PID %d - Thread 0x%lx #\n\n",
pid, tid);
#elif defined(G_OS_WIN32) || defined(SYS_gettid) || defined(HAVE_THR_SELF)
if (stream) if (stream)
g_fprintf (stream, g_fprintf (stream,
"\n# Stack traces obtained from PID %d - Thread %lu #\n\n", "\n# Stack traces obtained from PID %d - Thread %lu #\n\n",
@ -1376,11 +1422,7 @@ gimp_stack_trace_print (const gchar *prog_name,
if (trace) if (trace)
{ {
gtrace = g_string_new (NULL); gtrace = g_string_new (NULL);
#if defined(PLATFORM_OSX) #if defined(G_OS_WIN32) || defined(SYS_gettid) || defined(HAVE_THR_SELF)
g_string_printf (gtrace,
"\n# Stack traces obtained from PID %d - Thread 0x%lx #\n\n",
pid, tid);
#elif defined(G_OS_WIN32) || defined(SYS_gettid) || defined(HAVE_THR_SELF)
g_string_printf (gtrace, g_string_printf (gtrace,
"\n# Stack traces obtained from PID %d - Thread %lu #\n\n", "\n# Stack traces obtained from PID %d - Thread %lu #\n\n",
pid, tid); pid, tid);
@ -1469,6 +1511,7 @@ gimp_stack_trace_print (const gchar *prog_name,
#endif /* G_OS_WIN32 */ #endif /* G_OS_WIN32 */
return stack_printed; return stack_printed;
#endif /* PLATFORM_OSX */
} }
/** /**