app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
|
|
|
* Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2018-09-02 09:08:09 -04:00
|
|
|
* gimpbacktrace-linux.c
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
* Copyright (C) 2018 Ell
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2018-09-03 15:29:20 -04:00
|
|
|
#include <gio/gio.h>
|
|
|
|
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
#include "gimpbacktrace-backend.h"
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef GIMP_BACKTRACE_BACKEND_LINUX
|
|
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/syscall.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <execinfo.h>
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <string.h>
|
2018-09-03 18:13:16 -04:00
|
|
|
#include <stdio.h>
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-09-22 22:33:44 -04:00
|
|
|
#ifdef HAVE_LIBBACKTRACE
|
|
|
|
#include <backtrace.h>
|
|
|
|
#endif
|
|
|
|
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
#ifdef HAVE_LIBUNWIND
|
|
|
|
#define UNW_LOCAL_ONLY
|
|
|
|
#include <libunwind.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "core-types.h"
|
|
|
|
|
|
|
|
#include "gimpbacktrace.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define MAX_N_THREADS 256
|
|
|
|
#define MAX_N_FRAMES 256
|
|
|
|
#define MAX_THREAD_NAME_SIZE 32
|
|
|
|
#define N_SKIPPED_FRAMES 2
|
2018-11-07 14:08:17 -05:00
|
|
|
#define MAX_WAIT_TIME (G_TIME_SPAN_SECOND / 20)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
#define BACKTRACE_SIGNAL SIGUSR1
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct _GimpBacktraceThread GimpBacktraceThread;
|
|
|
|
|
|
|
|
|
|
|
|
struct _GimpBacktraceThread
|
|
|
|
{
|
|
|
|
pid_t tid;
|
|
|
|
gchar name[MAX_THREAD_NAME_SIZE];
|
2018-09-03 18:13:16 -04:00
|
|
|
gchar state;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
|
|
|
guintptr frames[MAX_N_FRAMES];
|
|
|
|
gint n_frames;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _GimpBacktrace
|
|
|
|
{
|
|
|
|
GimpBacktraceThread *threads;
|
|
|
|
gint n_threads;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
|
|
|
|
static inline gint gimp_backtrace_normalize_frame (GimpBacktrace *backtrace,
|
|
|
|
gint thread,
|
|
|
|
gint frame);
|
|
|
|
|
|
|
|
static gint gimp_backtrace_enumerate_threads (gboolean include_current_thread,
|
|
|
|
pid_t *threads,
|
|
|
|
gint size);
|
|
|
|
static void gimp_backtrace_read_thread_name (pid_t tid,
|
|
|
|
gchar *name,
|
|
|
|
gint size);
|
2018-09-03 18:13:16 -04:00
|
|
|
static gchar gimp_backtrace_read_thread_state (pid_t tid);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
|
|
|
static void gimp_backtrace_signal_handler (gint signum);
|
|
|
|
|
|
|
|
|
|
|
|
/* static variables */
|
|
|
|
|
|
|
|
static GMutex mutex;
|
|
|
|
static gint n_initializations;
|
|
|
|
static gboolean initialized;
|
|
|
|
static struct sigaction orig_action;
|
|
|
|
static pid_t blacklisted_threads[MAX_N_THREADS];
|
|
|
|
static gint n_blacklisted_threads;
|
|
|
|
static GimpBacktrace *handler_backtrace;
|
2018-12-01 04:29:49 -05:00
|
|
|
static gint handler_n_remaining_threads;
|
2018-11-07 14:08:17 -05:00
|
|
|
static gint handler_lock;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-09-22 22:33:44 -04:00
|
|
|
#ifdef HAVE_LIBBACKTRACE
|
|
|
|
static struct backtrace_state *backtrace_state;
|
|
|
|
#endif
|
|
|
|
|
2018-12-01 03:51:12 -05:00
|
|
|
static const gchar * const blacklisted_thread_names[] =
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
2018-11-07 14:08:17 -05:00
|
|
|
"gmain",
|
|
|
|
"threaded-ml"
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* private functions */
|
|
|
|
|
|
|
|
|
|
|
|
static inline gint
|
|
|
|
gimp_backtrace_normalize_frame (GimpBacktrace *backtrace,
|
|
|
|
gint thread,
|
|
|
|
gint frame)
|
|
|
|
{
|
|
|
|
if (frame >= 0)
|
|
|
|
return frame + N_SKIPPED_FRAMES;
|
|
|
|
else
|
|
|
|
return backtrace->threads[thread].n_frames + frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
gimp_backtrace_enumerate_threads (gboolean include_current_thread,
|
|
|
|
pid_t *threads,
|
|
|
|
gint size)
|
|
|
|
{
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *dirent;
|
|
|
|
pid_t tid;
|
|
|
|
gint n_threads;
|
|
|
|
|
|
|
|
dir = opendir ("/proc/self/task");
|
|
|
|
|
|
|
|
if (! dir)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
tid = syscall (SYS_gettid);
|
|
|
|
|
|
|
|
n_threads = 0;
|
|
|
|
|
|
|
|
while (n_threads < size && (dirent = readdir (dir)))
|
|
|
|
{
|
|
|
|
pid_t id = g_ascii_strtoull (dirent->d_name, NULL, 10);
|
|
|
|
|
|
|
|
if (id)
|
|
|
|
{
|
|
|
|
if (! include_current_thread && id == tid)
|
|
|
|
id = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
for (i = 0; i < n_blacklisted_threads; i++)
|
|
|
|
{
|
|
|
|
if (id == blacklisted_threads[i])
|
|
|
|
{
|
|
|
|
id = 0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id)
|
|
|
|
threads[n_threads++] = id;
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir (dir);
|
|
|
|
|
|
|
|
return n_threads;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_backtrace_read_thread_name (pid_t tid,
|
|
|
|
gchar *name,
|
|
|
|
gint size)
|
|
|
|
{
|
|
|
|
gchar filename[64];
|
|
|
|
gint fd;
|
|
|
|
|
|
|
|
if (size <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
name[0] = '\0';
|
|
|
|
|
|
|
|
g_snprintf (filename, sizeof (filename),
|
|
|
|
"/proc/self/task/%llu/comm",
|
|
|
|
(unsigned long long) tid);
|
|
|
|
|
|
|
|
fd = open (filename, O_RDONLY);
|
|
|
|
|
|
|
|
if (fd >= 0)
|
|
|
|
{
|
|
|
|
gint n = read (fd, name, size);
|
|
|
|
|
|
|
|
if (n > 0)
|
|
|
|
name[n - 1] = '\0';
|
|
|
|
|
|
|
|
close (fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-03 18:13:16 -04:00
|
|
|
static gchar
|
|
|
|
gimp_backtrace_read_thread_state (pid_t tid)
|
|
|
|
{
|
|
|
|
gchar buffer[64];
|
|
|
|
gint fd;
|
|
|
|
gchar state = '\0';
|
|
|
|
|
|
|
|
g_snprintf (buffer, sizeof (buffer),
|
|
|
|
"/proc/self/task/%llu/stat",
|
|
|
|
(unsigned long long) tid);
|
|
|
|
|
|
|
|
fd = open (buffer, O_RDONLY);
|
|
|
|
|
|
|
|
if (fd >= 0)
|
|
|
|
{
|
|
|
|
gint n = read (fd, buffer, sizeof (buffer));
|
|
|
|
|
|
|
|
if (n > 0)
|
|
|
|
buffer[n - 1] = '\0';
|
|
|
|
|
|
|
|
sscanf (buffer, "%*d %*s %c", &state);
|
|
|
|
|
|
|
|
close (fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
static void
|
|
|
|
gimp_backtrace_signal_handler (gint signum)
|
|
|
|
{
|
2018-11-07 14:08:17 -05:00
|
|
|
GimpBacktrace *curr_backtrace;
|
|
|
|
gint lock;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
do
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
2018-11-07 14:08:17 -05:00
|
|
|
lock = g_atomic_int_get (&handler_lock);
|
|
|
|
|
|
|
|
if (lock < 0)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
while (! g_atomic_int_compare_and_exchange (&handler_lock, lock, lock + 1));
|
|
|
|
|
|
|
|
curr_backtrace = g_atomic_pointer_get (&handler_backtrace);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
if (curr_backtrace)
|
|
|
|
{
|
|
|
|
pid_t tid = syscall (SYS_gettid);
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
for (i = 0; i < curr_backtrace->n_threads; i++)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
2018-11-07 14:08:17 -05:00
|
|
|
GimpBacktraceThread *thread = &curr_backtrace->threads[i];
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
if (thread->tid == tid)
|
|
|
|
{
|
|
|
|
thread->n_frames = backtrace ((gpointer *) thread->frames,
|
|
|
|
MAX_N_FRAMES);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-12-01 04:29:49 -05:00
|
|
|
g_atomic_int_dec_and_test (&handler_n_remaining_threads);
|
2018-11-07 14:08:17 -05:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
|
|
|
}
|
2018-11-07 14:08:17 -05:00
|
|
|
|
|
|
|
g_atomic_int_dec_and_test (&handler_lock);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
|
|
|
|
2018-09-03 15:29:20 -04:00
|
|
|
void
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
gimp_backtrace_init (void)
|
2018-09-03 15:29:20 -04:00
|
|
|
{
|
2018-09-22 22:33:44 -04:00
|
|
|
#ifdef HAVE_LIBBACKTRACE
|
|
|
|
backtrace_state = backtrace_create_state (NULL, 0, NULL, NULL);
|
|
|
|
#endif
|
2018-09-03 15:29:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_backtrace_start (void)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
|
|
|
g_mutex_lock (&mutex);
|
|
|
|
|
|
|
|
if (n_initializations == 0)
|
|
|
|
{
|
|
|
|
struct sigaction action = {};
|
|
|
|
|
|
|
|
action.sa_handler = gimp_backtrace_signal_handler;
|
2018-09-16 08:54:18 -04:00
|
|
|
action.sa_flags = SA_RESTART;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
|
|
|
sigemptyset (&action.sa_mask);
|
|
|
|
|
|
|
|
if (sigaction (BACKTRACE_SIGNAL, &action, &orig_action) == 0)
|
|
|
|
{
|
|
|
|
pid_t *threads;
|
|
|
|
gint n_threads;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
n_blacklisted_threads = 0;
|
|
|
|
|
|
|
|
threads = g_new (pid_t, MAX_N_THREADS);
|
|
|
|
|
|
|
|
n_threads = gimp_backtrace_enumerate_threads (TRUE,
|
|
|
|
threads, MAX_N_THREADS);
|
|
|
|
|
|
|
|
for (i = 0; i < n_threads; i++)
|
|
|
|
{
|
|
|
|
gchar name[MAX_THREAD_NAME_SIZE];
|
|
|
|
gint j;
|
|
|
|
|
|
|
|
gimp_backtrace_read_thread_name (threads[i],
|
|
|
|
name, MAX_THREAD_NAME_SIZE);
|
|
|
|
|
|
|
|
for (j = 0; j < G_N_ELEMENTS (blacklisted_thread_names); j++)
|
|
|
|
{
|
|
|
|
if (! strcmp (name, blacklisted_thread_names[j]))
|
|
|
|
{
|
|
|
|
blacklisted_threads[n_blacklisted_threads++] = threads[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (threads);
|
|
|
|
|
|
|
|
initialized = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
n_initializations++;
|
|
|
|
|
|
|
|
g_mutex_unlock (&mutex);
|
|
|
|
|
|
|
|
return initialized;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-09-03 15:29:20 -04:00
|
|
|
gimp_backtrace_stop (void)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
|
|
|
g_return_if_fail (n_initializations > 0);
|
|
|
|
|
|
|
|
g_mutex_lock (&mutex);
|
|
|
|
|
|
|
|
n_initializations--;
|
|
|
|
|
|
|
|
if (n_initializations == 0 && initialized)
|
|
|
|
{
|
|
|
|
if (sigaction (BACKTRACE_SIGNAL, &orig_action, NULL) < 0)
|
Fix typos
Found via:
```
codespell -q 3 -S ./ChangeLog*,*.po,./.git,./NEWS* -L als,ang,ba,chello,daa,doubleclick,foto,hist,iff,inport,klass,mut,nd,ower,paeth,params,pard,pevent,sinc,thru,tim,uint
```
2020-11-05 11:43:53 -05:00
|
|
|
g_warning ("failed to restore original backtrace signal handler");
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
|
|
|
initialized = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_mutex_unlock (&mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
GimpBacktrace *
|
|
|
|
gimp_backtrace_new (gboolean include_current_thread)
|
|
|
|
{
|
|
|
|
GimpBacktrace *backtrace;
|
|
|
|
pid_t pid;
|
|
|
|
pid_t *threads;
|
|
|
|
gint n_threads;
|
|
|
|
gint64 start_time;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
if (! initialized)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pid = getpid ();
|
|
|
|
|
|
|
|
threads = g_new (pid_t, MAX_N_THREADS);
|
|
|
|
|
|
|
|
n_threads = gimp_backtrace_enumerate_threads (include_current_thread,
|
|
|
|
threads, MAX_N_THREADS);
|
|
|
|
|
|
|
|
if (n_threads == 0)
|
|
|
|
{
|
|
|
|
g_free (threads);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_mutex_lock (&mutex);
|
|
|
|
|
|
|
|
backtrace = g_slice_new (GimpBacktrace);
|
|
|
|
|
2018-12-01 04:29:49 -05:00
|
|
|
backtrace->threads = g_new (GimpBacktraceThread, n_threads);
|
|
|
|
backtrace->n_threads = n_threads;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
while (! g_atomic_int_compare_and_exchange (&handler_lock, 0, -1));
|
|
|
|
|
2018-12-01 04:29:49 -05:00
|
|
|
g_atomic_pointer_set (&handler_backtrace, backtrace);
|
|
|
|
g_atomic_int_set (&handler_n_remaining_threads, n_threads);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
g_atomic_int_set (&handler_lock, 0);
|
|
|
|
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
for (i = 0; i < n_threads; i++)
|
|
|
|
{
|
|
|
|
GimpBacktraceThread *thread = &backtrace->threads[i];
|
|
|
|
|
|
|
|
thread->tid = threads[i];
|
|
|
|
thread->n_frames = 0;
|
|
|
|
|
|
|
|
gimp_backtrace_read_thread_name (thread->tid,
|
|
|
|
thread->name, MAX_THREAD_NAME_SIZE);
|
|
|
|
|
2018-09-03 18:13:16 -04:00
|
|
|
thread->state = gimp_backtrace_read_thread_state (thread->tid);
|
|
|
|
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
syscall (SYS_tgkill, pid, threads[i], BACKTRACE_SIGNAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (threads);
|
|
|
|
|
|
|
|
start_time = g_get_monotonic_time ();
|
|
|
|
|
2018-12-01 04:29:49 -05:00
|
|
|
while (g_atomic_int_get (&handler_n_remaining_threads) > 0)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
|
|
|
gint64 time = g_get_monotonic_time ();
|
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
if (time - start_time > MAX_WAIT_TIME)
|
|
|
|
break;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
g_usleep (1000);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
while (! g_atomic_int_compare_and_exchange (&handler_lock, 0, -1));
|
|
|
|
|
|
|
|
g_atomic_pointer_set (&handler_backtrace, NULL);
|
|
|
|
|
|
|
|
g_atomic_int_set (&handler_lock, 0);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
#if 0
|
2018-12-01 04:29:49 -05:00
|
|
|
if (handler_n_remaining_threads > 0)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
2018-11-07 14:08:17 -05:00
|
|
|
gint j = 0;
|
|
|
|
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
for (i = 0; i < n_threads; i++)
|
|
|
|
{
|
|
|
|
if (backtrace->threads[i].n_frames == 0)
|
|
|
|
{
|
|
|
|
if (n_blacklisted_threads < MAX_N_THREADS)
|
|
|
|
{
|
|
|
|
blacklisted_threads[n_blacklisted_threads++] =
|
|
|
|
backtrace->threads[i].tid;
|
|
|
|
}
|
2018-11-07 14:08:17 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (j < i)
|
|
|
|
backtrace->threads[j] = backtrace->threads[i];
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
j++;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
|
|
|
}
|
2018-11-07 14:08:17 -05:00
|
|
|
|
|
|
|
n_threads = j;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
2018-11-07 14:08:17 -05:00
|
|
|
#endif
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
|
|
|
g_mutex_unlock (&mutex);
|
|
|
|
|
|
|
|
if (n_threads == 0)
|
|
|
|
{
|
|
|
|
gimp_backtrace_free (backtrace);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return backtrace;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_backtrace_free (GimpBacktrace *backtrace)
|
|
|
|
{
|
2018-12-01 04:29:49 -05:00
|
|
|
if (! backtrace)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
return;
|
|
|
|
|
|
|
|
g_free (backtrace->threads);
|
|
|
|
|
|
|
|
g_slice_free (GimpBacktrace, backtrace);
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
gimp_backtrace_get_n_threads (GimpBacktrace *backtrace)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (backtrace != NULL, 0);
|
|
|
|
|
|
|
|
return backtrace->n_threads;
|
|
|
|
}
|
|
|
|
|
|
|
|
guintptr
|
|
|
|
gimp_backtrace_get_thread_id (GimpBacktrace *backtrace,
|
|
|
|
gint thread)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (backtrace != NULL, 0);
|
|
|
|
g_return_val_if_fail (thread >= 0 && thread < backtrace->n_threads, 0);
|
|
|
|
|
|
|
|
return backtrace->threads[thread].tid;
|
|
|
|
}
|
|
|
|
|
|
|
|
const gchar *
|
|
|
|
gimp_backtrace_get_thread_name (GimpBacktrace *backtrace,
|
|
|
|
gint thread)
|
|
|
|
{
|
2018-09-03 18:13:16 -04:00
|
|
|
g_return_val_if_fail (backtrace != NULL, NULL);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
g_return_val_if_fail (thread >= 0 && thread < backtrace->n_threads, NULL);
|
|
|
|
|
|
|
|
if (backtrace->threads[thread].name[0])
|
|
|
|
return backtrace->threads[thread].name;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-09-03 18:13:16 -04:00
|
|
|
gboolean
|
|
|
|
gimp_backtrace_is_thread_running (GimpBacktrace *backtrace,
|
|
|
|
gint thread)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (backtrace != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (thread >= 0 && thread < backtrace->n_threads, FALSE);
|
|
|
|
|
|
|
|
return backtrace->threads[thread].state == 'R';
|
|
|
|
}
|
|
|
|
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
gint
|
|
|
|
gimp_backtrace_find_thread_by_id (GimpBacktrace *backtrace,
|
|
|
|
guintptr thread_id,
|
|
|
|
gint thread_hint)
|
|
|
|
{
|
|
|
|
pid_t tid = thread_id;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
g_return_val_if_fail (backtrace != NULL, -1);
|
|
|
|
|
2018-09-05 14:48:59 -04:00
|
|
|
if (thread_hint >= 0 &&
|
|
|
|
thread_hint < backtrace->n_threads &&
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
backtrace->threads[thread_hint].tid == tid)
|
|
|
|
{
|
|
|
|
return thread_hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < backtrace->n_threads; i++)
|
|
|
|
{
|
|
|
|
if (backtrace->threads[i].tid == tid)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
gimp_backtrace_get_n_frames (GimpBacktrace *backtrace,
|
|
|
|
gint thread)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (backtrace != NULL, 0);
|
|
|
|
g_return_val_if_fail (thread >= 0 && thread < backtrace->n_threads, 0);
|
|
|
|
|
2018-11-07 14:08:17 -05:00
|
|
|
return MAX (backtrace->threads[thread].n_frames - N_SKIPPED_FRAMES, 0);
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
guintptr
|
|
|
|
gimp_backtrace_get_frame_address (GimpBacktrace *backtrace,
|
|
|
|
gint thread,
|
|
|
|
gint frame)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (backtrace != NULL, 0);
|
|
|
|
g_return_val_if_fail (thread >= 0 && thread < backtrace->n_threads, 0);
|
|
|
|
|
|
|
|
frame = gimp_backtrace_normalize_frame (backtrace, thread, frame);
|
|
|
|
|
|
|
|
g_return_val_if_fail (frame >= N_SKIPPED_FRAMES &&
|
|
|
|
frame < backtrace->threads[thread].n_frames, 0);
|
|
|
|
|
|
|
|
return backtrace->threads[thread].frames[frame];
|
|
|
|
}
|
|
|
|
|
2018-09-22 22:33:44 -04:00
|
|
|
#ifdef HAVE_LIBBACKTRACE
|
|
|
|
static void
|
|
|
|
gimp_backtrace_syminfo_callback (GimpBacktraceAddressInfo *info,
|
|
|
|
guintptr pc,
|
|
|
|
const gchar *symname,
|
|
|
|
guintptr symval,
|
|
|
|
guintptr symsize)
|
|
|
|
{
|
|
|
|
if (symname)
|
|
|
|
g_strlcpy (info->symbol_name, symname, sizeof (info->symbol_name));
|
|
|
|
|
|
|
|
info->symbol_address = symval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
gimp_backtrace_pcinfo_callback (GimpBacktraceAddressInfo *info,
|
|
|
|
guintptr pc,
|
|
|
|
const gchar *filename,
|
|
|
|
gint lineno,
|
|
|
|
const gchar *function)
|
|
|
|
{
|
|
|
|
if (function)
|
|
|
|
g_strlcpy (info->symbol_name, function, sizeof (info->symbol_name));
|
|
|
|
|
|
|
|
if (filename)
|
|
|
|
g_strlcpy (info->source_file, filename, sizeof (info->source_file));
|
|
|
|
|
|
|
|
info->source_line = lineno;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_LIBBACKTRACE */
|
|
|
|
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
gboolean
|
2018-09-02 13:22:27 -04:00
|
|
|
gimp_backtrace_get_address_info (guintptr address,
|
|
|
|
GimpBacktraceAddressInfo *info)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
2018-09-22 22:33:44 -04:00
|
|
|
Dl_info dl_info;
|
|
|
|
gboolean result = FALSE;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
|
|
|
g_return_val_if_fail (info != NULL, FALSE);
|
|
|
|
|
2018-09-22 22:33:44 -04:00
|
|
|
info->object_name[0] = '\0';
|
|
|
|
|
|
|
|
info->symbol_name[0] = '\0';
|
|
|
|
info->symbol_address = 0;
|
|
|
|
|
|
|
|
info->source_file[0] = '\0';
|
|
|
|
info->source_line = 0;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-09-22 22:33:44 -04:00
|
|
|
if (dladdr ((gpointer) address, &dl_info))
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
2018-09-22 22:33:44 -04:00
|
|
|
if (dl_info.dli_fname)
|
|
|
|
{
|
|
|
|
g_strlcpy (info->object_name, dl_info.dli_fname,
|
|
|
|
sizeof (info->object_name));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dl_info.dli_sname)
|
|
|
|
{
|
|
|
|
g_strlcpy (info->symbol_name, dl_info.dli_sname,
|
|
|
|
sizeof (info->symbol_name));
|
|
|
|
}
|
|
|
|
|
|
|
|
info->symbol_address = (guintptr) dl_info.dli_saddr;
|
|
|
|
|
|
|
|
result = TRUE;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
2018-09-22 22:33:44 -04:00
|
|
|
|
|
|
|
#ifdef HAVE_LIBBACKTRACE
|
|
|
|
if (backtrace_state)
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
{
|
2018-09-22 22:33:44 -04:00
|
|
|
backtrace_syminfo (
|
|
|
|
backtrace_state, address,
|
|
|
|
(backtrace_syminfo_callback) gimp_backtrace_syminfo_callback,
|
|
|
|
NULL,
|
|
|
|
info);
|
|
|
|
|
|
|
|
backtrace_pcinfo (
|
|
|
|
backtrace_state, address,
|
|
|
|
(backtrace_full_callback) gimp_backtrace_pcinfo_callback,
|
|
|
|
NULL,
|
|
|
|
info);
|
|
|
|
|
|
|
|
result = TRUE;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
2018-09-22 22:33:44 -04:00
|
|
|
#endif /* HAVE_LIBBACKTRACE */
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-09-22 22:33:44 -04:00
|
|
|
#ifdef HAVE_LIBUNWIND
|
app: always use libunwind for symbol names in GimpBacktrace Linux backend
In the GimpBacktrace Linux backend, always use libunwind, when
available, to find symbol names, even if dladdr() or libbacktrace
had already found one. libunwind provides more descriptive names
in certain cases, and, in particular, full symbol names for C++
lambdas.
Note that, in some cases, this can result in a discrepancy between
the reported symbol name, and the corresponding source location.
2018-10-11 03:31:57 -04:00
|
|
|
/* we use libunwind to get the symbol name, when available, even if dladdr() or
|
|
|
|
* libbacktrace already found one, since it provides more descriptive names in
|
|
|
|
* some cases, and, in particular, full symbol names for C++ lambdas.
|
|
|
|
*
|
|
|
|
* note that, in some cases, this can result in a discrepancy between the
|
|
|
|
* symbol name, and the corresponding source location.
|
|
|
|
*/
|
|
|
|
#if 0
|
2018-09-22 22:33:44 -04:00
|
|
|
if (! info->symbol_name[0])
|
app: always use libunwind for symbol names in GimpBacktrace Linux backend
In the GimpBacktrace Linux backend, always use libunwind, when
available, to find symbol names, even if dladdr() or libbacktrace
had already found one. libunwind provides more descriptive names
in certain cases, and, in particular, full symbol names for C++
lambdas.
Note that, in some cases, this can result in a discrepancy between
the reported symbol name, and the corresponding source location.
2018-10-11 03:31:57 -04:00
|
|
|
#endif
|
2018-09-22 22:33:44 -04:00
|
|
|
{
|
|
|
|
unw_context_t context = {};
|
|
|
|
unw_cursor_t cursor;
|
|
|
|
unw_word_t offset;
|
|
|
|
|
|
|
|
if (unw_init_local (&cursor, &context) == 0 &&
|
|
|
|
unw_set_reg (&cursor, UNW_REG_IP, address) == 0 &&
|
|
|
|
unw_get_proc_name (&cursor,
|
|
|
|
info->symbol_name, sizeof (info->symbol_name),
|
|
|
|
&offset) == 0)
|
|
|
|
{
|
|
|
|
info->symbol_address = address - offset;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
|
2018-09-22 22:33:44 -04:00
|
|
|
result = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_LIBUNWIND */
|
2018-09-03 15:34:39 -04:00
|
|
|
|
2018-09-22 22:33:44 -04:00
|
|
|
return result;
|
app: add GimpBacktrace
GimpBacktrace provides an interface for creating and traversing
multi-threaded backtraces, as well as querying symbol information.
While we already have some backtrace functionality, it relies on
external tools for the most part, and as such is rather expensive,
and is only meant for producing opaque backtraces. GimpBacktrace,
on the other hand, is meant to be relatively cheap (we're going to
use it for profiling,) and allow inspection of the backtrace data.
In the future, it might make sense to replace some, or all, of the
other backtrace functions with GimpBacktrace.
GimpBacktrace currently only supports Linux. By default, it uses
dladdr() to query symbol information, which is somewhat limited (in
particular, it doesn't work for static functions.) When libunwind
is installed, GimpBacktrace uses it to get more complete symbol
information. libunwind is currently an optional dependency, but it
might make sense to promote it to a mandatory, or opt-out,
dependency, as it's lightweight and widely available.
On other platforms, the GimpBacktrace interface can still be used,
but it always returns NULL backtraces.
2018-09-02 01:15:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* GIMP_BACKTRACE_BACKEND_LINUX */
|