[glib: 1/2] gbacktrace: on macOS support and default to LLDB



commit 1fbd185430f31adaa325e6a78c5d5aeb517ce3c1
Author: Kristian Rietveld <kris loopnest org>
Date:   Fri Mar 6 22:40:40 2015 +0100

    gbacktrace: on macOS support and default to LLDB
    
    Tweaked by Philip Withnall <withnall endlessm com> to fix review issues.
    
    Closes: #1004

 glib/gbacktrace.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 49 insertions(+), 7 deletions(-)
---
diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c
index 86f884170..479ae4281 100644
--- a/glib/gbacktrace.c
+++ b/glib/gbacktrace.c
@@ -72,6 +72,17 @@
 static void stack_trace (const char * const *args);
 #endif
 
+/* Default to using LLDB for backtraces on macOS. */
+#ifdef __APPLE__
+#define USE_LLDB
+#endif
+
+#ifdef USE_LLDB
+#define DEBUGGER "lldb"
+#else
+#define DEBUGGER "gdb"
+#endif
+
 /* People want to hit this from their debugger... */
 GLIB_AVAILABLE_IN_ALL volatile gboolean glib_on_error_halt;
 volatile gboolean glib_on_error_halt = TRUE;
@@ -231,7 +242,7 @@ g_on_error_stack_trace (const gchar *prg_name)
 #if defined(G_OS_UNIX)
   pid_t pid;
   gchar buf[16];
-  const gchar *args[4] = { "gdb", NULL, NULL, NULL };
+  const gchar *args[5] = { DEBUGGER, NULL, NULL, NULL, NULL };
   int status;
 
   if (!prg_name)
@@ -239,8 +250,14 @@ g_on_error_stack_trace (const gchar *prg_name)
 
   _g_sprintf (buf, "%u", (guint) getpid ());
 
+#ifdef USE_LLDB
+  args[1] = prg_name;
+  args[2] = "-p";
+  args[3] = buf;
+#else
   args[1] = prg_name;
   args[2] = buf;
+#endif
 
   pid = fork ();
   if (pid == 0)
@@ -250,11 +267,19 @@ g_on_error_stack_trace (const gchar *prg_name)
     }
   else if (pid == (pid_t) -1)
     {
-      perror ("unable to fork gdb");
+      perror ("unable to fork " DEBUGGER);
       return;
     }
 
-  waitpid (pid, &status, 0);
+  /* Wait until the child really terminates. On Mac OS X waitpid ()
+   * will also return when the child is being stopped due to tracing.
+   */
+  while (1)
+    {
+      pid_t retval = waitpid (pid, &status, 0);
+      if (WIFEXITED (retval) || WIFSIGNALED (retval))
+        break;
+    }
 #else
   if (IsDebuggerPresent ())
     G_BREAKPOINT ();
@@ -273,6 +298,8 @@ stack_trace_sigchld (int signum)
   stack_trace_done = TRUE;
 }
 
+#define BUFSIZE 1024
+
 static void
 stack_trace (const char * const *args)
 {
@@ -282,8 +309,8 @@ stack_trace (const char * const *args)
   fd_set fdset;
   fd_set readset;
   struct timeval tv;
-  int sel, idx, state;
-  char buffer[256];
+  int sel, idx, state, line_idx;
+  char buffer[BUFSIZE];
   char c;
 
   stack_trace_done = FALSE;
@@ -315,7 +342,7 @@ stack_trace (const char * const *args)
           close (2);
           dup (old_err);
         }
-      perror ("exec gdb failed");
+      perror ("exec " DEBUGGER " failed");
       _exit (0);
     }
   else if (pid == (pid_t) -1)
@@ -327,11 +354,19 @@ stack_trace (const char * const *args)
   FD_ZERO (&fdset);
   FD_SET (out_fd[0], &fdset);
 
+#ifdef USE_LLDB
+  write (in_fd[1], "bt\n", 3);
+  write (in_fd[1], "p x = 0\n", 8);
+  write (in_fd[1], "process detach\n", 15);
+  write (in_fd[1], "quit\n", 5);
+#else
   write (in_fd[1], "backtrace\n", 10);
   write (in_fd[1], "p x = 0\n", 8);
   write (in_fd[1], "quit\n", 5);
+#endif
 
   idx = 0;
+  line_idx = 0;
   state = 0;
 
   while (1)
@@ -348,10 +383,15 @@ stack_trace (const char * const *args)
         {
           if (read (out_fd[0], &c, 1))
             {
+              line_idx += 1;
               switch (state)
                 {
                 case 0:
+#ifdef USE_LLDB
+                  if (c == '*' || (c == ' ' && line_idx == 1))
+#else
                   if (c == '#')
+#endif
                     {
                       state = 1;
                       idx = 0;
@@ -359,13 +399,15 @@ stack_trace (const char * const *args)
                     }
                   break;
                 case 1:
-                  buffer[idx++] = c;
+                  if (idx < BUFSIZE)
+                    buffer[idx++] = c;
                   if ((c == '\n') || (c == '\r'))
                     {
                       buffer[idx] = 0;
                       _g_fprintf (stdout, "%s", buffer);
                       state = 0;
                       idx = 0;
+                      line_idx = 0;
                     }
                   break;
                 default:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]