[gimp] libgimpbase: improve multi-threaded stack traces.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimpbase: improve multi-threaded stack traces.
- Date: Tue, 10 Apr 2018 12:51:36 +0000 (UTC)
commit ae6a7bf98f409d184e13ddfd18581777339c45eb
Author: Jehan <jehan girinstud io>
Date: Tue Apr 10 14:36:51 2018 +0200
libgimpbase: improve multi-threaded stack traces.
Since commit bb52431cdd, we get multi-thread traces in functions
gimp_stack_trace_*(). Adding now the LLDB equivalent improvement.
Also adding the process and thread id information, from which the trace
order was made, atop the listing, as well as the thread list. This would
allow to easily find and associate the threads.
The problem is that sometimes the thread where we got a trace from may
not matter (for instance signals, even such as SIGABRT or SIGSEGV, seem
to sent a bit randomly to either the thread which provoked them or the
main thread; there is a bit of contradictory info on this when reading
on the topic, in my case I experienced this), in such case, getting all
thread stack is important to find the origin of the signal.
Other times it will highly matter, in particular when getting a trace
for a WARNING or CRITICAL. This information will help to discriminate
between thread traces.
libgimpbase/gimputils.c | 70 +++++++++++++++++++++++++++++++++--------------
1 files changed, 49 insertions(+), 21 deletions(-)
---
diff --git a/libgimpbase/gimputils.c b/libgimpbase/gimputils.c
index c2fbbe9..eb2c5ad 100644
--- a/libgimpbase/gimputils.c
+++ b/libgimpbase/gimputils.c
@@ -38,6 +38,7 @@
#include <glib/gprintf.h>
#if defined(G_OS_WIN32)
+
/* This is a hack for Windows known directory support.
* DATADIR (autotools-generated constant) is a type defined in objidl.h
* so we must #undef it before including shlobj.h in order to avoid a
@@ -45,15 +46,22 @@
#undef DATADIR
#include <windows.h>
#include <shlobj.h>
+
#else /* G_OS_WIN32 */
+
/* For waitpid() */
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
+/* For thread IDs. */
+#include <sys/types.h>
+#include <sys/syscall.h>
+
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
+
#endif /* G_OS_WIN32 */
#include "gimpbasetypes.h"
@@ -1152,9 +1160,9 @@ gimp_stack_trace_available (gboolean optimal)
* Since: 2.10
**/
gboolean
-gimp_stack_trace_print (const gchar *prog_name,
- gpointer stream,
- gchar **trace)
+gimp_stack_trace_print (const gchar *prog_name,
+ gpointer stream,
+ gchar **trace)
{
gboolean stack_printed = FALSE;
@@ -1162,13 +1170,19 @@ gimp_stack_trace_print (const gchar *prog_name,
#ifndef G_OS_WIN32
GString *gtrace = NULL;
gchar gimp_pid[16];
- pid_t pid;
gchar buffer[256];
ssize_t read_n;
int sync_fd[2];
int out_fd[2];
+ pid_t fork_pid;
+ pid_t pid = getpid();
+#if defined(G_OS_WIN32)
+ DWORD tid = GetCurrentThreadId ();
+#else
+ long tid = syscall (SYS_gettid);
+#endif
- g_snprintf (gimp_pid, 16, "%u", (guint) getpid ());
+ g_snprintf (gimp_pid, 16, "%u", (guint) pid);
if (pipe (sync_fd) == -1)
{
@@ -1183,17 +1197,19 @@ gimp_stack_trace_print (const gchar *prog_name,
return FALSE;
}
- pid = fork ();
- if (pid == 0)
+ fork_pid = fork ();
+ if (fork_pid == 0)
{
/* Child process. */
- gchar *args[7] = { "gdb", "-batch", "-ex", "thread apply all backtrace full",
+ gchar *args[9] = { "gdb", "-batch",
+ "-ex", "info threads",
+ "-ex", "thread apply all backtrace full",
(gchar *) prog_name, NULL, NULL };
if (prog_name == NULL)
- args[4] = "-p";
+ args[6] = "-p";
- args[5] = gimp_pid;
+ args[7] = gimp_pid;
/* Wait until the parent enabled us to ptrace it. */
{
@@ -1220,8 +1236,10 @@ gimp_stack_trace_print (const gchar *prog_name,
{
/* LLDB as alternative if the GDB call failed or if it was in
* a too-old version. */
- gchar *args_lldb[11] = { "lldb", "--attach-pid", NULL, "--batch",
- "--one-line", "bt",
+ gchar *args_lldb[15] = { "lldb", "--attach-pid", NULL, "--batch",
+ "--one-line", "thread list",
+ "--one-line", "thread backtrace all",
+ "--one-line", "bt all",
"--one-line-on-crash", "bt",
"--one-line-on-crash", "quit", NULL };
@@ -1232,7 +1250,7 @@ gimp_stack_trace_print (const gchar *prog_name,
_exit (0);
}
- else if (pid > 0)
+ else if (fork_pid > 0)
{
/* Main process */
int status;
@@ -1240,7 +1258,7 @@ gimp_stack_trace_print (const gchar *prog_name,
/* Allow the child to ptrace us, and signal it to start. */
close (sync_fd[0]);
#ifdef PR_SET_PTRACER
- prctl (PR_SET_PTRACER, pid, 0, 0, 0);
+ prctl (PR_SET_PTRACER, fork_pid, 0, 0, 0);
#endif
close (sync_fd[1]);
@@ -1252,6 +1270,20 @@ gimp_stack_trace_print (const gchar *prog_name,
while ((read_n = read (out_fd[0], buffer, 256)) > 0)
{
+ if (! stack_printed)
+ {
+ if (stream)
+ g_fprintf (stream,
+ "\n# Stack traces obtained from PID %d - Thread %lu #\n\n",
+ pid, tid);
+ if (trace)
+ {
+ gtrace = g_string_new (NULL);
+ g_string_printf (gtrace,
+ "\n# Stack traces obtained from PID %d - Thread %lu #\n\n",
+ pid, tid);
+ }
+ }
/* It's hard to know if the debugger was found since it
* happened in the child. Let's just assume that any output
* means it succeeded.
@@ -1262,11 +1294,7 @@ gimp_stack_trace_print (const gchar *prog_name,
if (stream)
g_fprintf (stream, "%s", buffer);
if (trace)
- {
- if (! gtrace)
- gtrace = g_string_new (NULL);
- g_string_append (gtrace, (const gchar *) buffer);
- }
+ g_string_append (gtrace, (const gchar *) buffer);
}
close (out_fd[0]);
@@ -1275,9 +1303,9 @@ gimp_stack_trace_print (const gchar *prog_name,
prctl (PR_SET_PTRACER, 0, 0, 0, 0);
#endif
- waitpid (pid, &status, 0);
+ waitpid (fork_pid, &status, 0);
}
- /* else if (pid == (pid_t) -1)
+ /* else if (fork_pid == (pid_t) -1)
* Fork failed!
* Just continue, maybe the backtrace() API will succeed.
*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]