[evolution-data-server] Move e_pointer_tracker to camel
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Move e_pointer_tracker to camel
- Date: Thu, 26 Jul 2012 16:43:34 +0000 (UTC)
commit e54481ecc147ddace454ccce6a06d27ff560252b
Author: Milan Crha <mcrha redhat com>
Date: Thu Jul 26 18:42:30 2012 +0200
Move e_pointer_tracker to camel
Thus it can be used in camel (and elsewhere) again.
camel/Makefile.am | 3 +-
camel/camel-debug.c | 425 +++++++++++++++++++++++++++++++++++
camel/camel-debug.h | 23 ++
configure.ac | 2 +-
libedataserver/Makefile.am | 3 +-
libedataserver/e-data-server-util.c | 402 ---------------------------------
libedataserver/e-data-server-util.h | 14 --
7 files changed, 452 insertions(+), 420 deletions(-)
---
diff --git a/camel/Makefile.am b/camel/Makefile.am
index 031eb38..5815d70 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -329,7 +329,8 @@ libcamel_1_2_la_LIBADD = \
$(CAMEL_LIBS) \
$(SOCKET_LIBS) \
$(ICONV_LIBS) \
- $(REGEX_LIBS)
+ $(REGEX_LIBS) \
+ $(LIBDWFL_LIBS)
camel_lock_helper_1_2_CPPFLAGS = \
$(AM_CPPFLAGS) \
diff --git a/camel/camel-debug.c b/camel/camel-debug.c
index 6509475..4f35e1b 100644
--- a/camel/camel-debug.c
+++ b/camel/camel-debug.c
@@ -19,10 +19,23 @@
* USA
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef HAVE_BACKTRACE_SYMBOLS
+#include <execinfo.h>
+#ifdef HAVE_ELFUTILS_LIBDWFL
+#include <elfutils/libdwfl.h>
+#include <errno.h>
+#include <unistd.h>
+#endif
+#endif
+
#include "camel-debug.h"
gint camel_verbose_debug;
@@ -247,3 +260,415 @@ camel_debug_hwatch (gint wp,
}
#endif
+
+G_LOCK_DEFINE_STATIC (ptr_tracker);
+static GHashTable *ptr_tracker = NULL;
+
+struct pt_data {
+ gpointer ptr;
+ gchar *info;
+ GString *backtrace;
+};
+
+static void
+free_pt_data (gpointer ptr)
+{
+ struct pt_data *ptd = ptr;
+
+ if (!ptd)
+ return;
+
+ g_free (ptd->info);
+ if (ptd->backtrace)
+ g_string_free (ptd->backtrace, TRUE);
+ g_free (ptd);
+}
+
+static void
+dump_left_ptrs_cb (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ guint *left = user_data;
+ struct pt_data *ptd = value;
+ gboolean have_info = ptd && ptd->info;
+ gboolean have_bt = ptd && ptd->backtrace && ptd->backtrace->str && *ptd->backtrace->str;
+
+ *left = (*left) - 1;
+ g_print (" %p %s%s%s%s%s%s\n", key, have_info ? "(" : "", have_info ? ptd->info : "", have_info ? ")" : "", have_bt ? "\n" : "", have_bt ? ptd->backtrace->str : "", have_bt && *left > 0 ? "\n" : "");
+}
+
+#ifdef HAVE_BACKTRACE_SYMBOLS
+static guint
+by_backtrace_hash (gconstpointer ptr)
+{
+ const struct pt_data *ptd = ptr;
+
+ if (!ptd || !ptd->backtrace)
+ return 0;
+
+ return g_str_hash (ptd->backtrace->str);
+}
+
+static gboolean
+by_backtrace_equal (gconstpointer ptr1,
+ gconstpointer ptr2)
+{
+ const struct pt_data *ptd1 = ptr1, *ptd2 = ptr2;
+
+ if ((!ptd1 || !ptd1->backtrace) && (!ptd2 || !ptd2->backtrace))
+ return TRUE;
+
+ return ptd1 && ptd1->backtrace && ptd2 && ptd2->backtrace && g_str_equal (ptd1->backtrace->str, ptd2->backtrace->str);
+}
+
+static void
+dump_by_backtrace_cb (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ guint *left = user_data;
+ struct pt_data *ptd = key;
+ guint count = GPOINTER_TO_UINT (value);
+
+ if (count == 1) {
+ dump_left_ptrs_cb (ptd->ptr, ptd, left);
+ } else {
+ gboolean have_info = ptd && ptd->info;
+ gboolean have_bt = ptd && ptd->backtrace && ptd->backtrace->str && *ptd->backtrace->str;
+
+ *left = (*left) - 1;
+
+ g_print (" %d x %s%s%s%s%s%s\n", count, have_info ? "(" : "", have_info ? ptd->info : "", have_info ? ")" : "", have_bt ? "\n" : "", have_bt ? ptd->backtrace->str : "", have_bt && *left > 0 ? "\n" : "");
+ }
+}
+
+static void
+dump_by_backtrace (GHashTable *ptrs)
+{
+ GHashTable *by_bt = g_hash_table_new (by_backtrace_hash, by_backtrace_equal);
+ GHashTableIter iter;
+ gpointer key, value;
+ struct ptr_data *ptd;
+ guint count;
+
+ g_hash_table_iter_init (&iter, ptrs);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ guint cnt;
+
+ ptd = value;
+ if (!ptd)
+ continue;
+
+ cnt = GPOINTER_TO_UINT (g_hash_table_lookup (by_bt, ptd));
+ cnt++;
+
+ g_hash_table_insert (by_bt, ptd, GUINT_TO_POINTER (cnt));
+ }
+
+ count = g_hash_table_size (by_bt);
+ g_hash_table_foreach (by_bt, dump_by_backtrace_cb, &count);
+ g_hash_table_destroy (by_bt);
+}
+#endif /* HAVE_BACKTRACE_SYMBOLS */
+
+static void
+dump_tracked_ptrs (gboolean is_at_exit)
+{
+ G_LOCK (ptr_tracker);
+
+ if (ptr_tracker) {
+ g_print ("\n----------------------------------------------------------\n");
+ if (g_hash_table_size (ptr_tracker) == 0) {
+ g_print (" All tracked pointers were properly removed\n");
+ } else {
+ guint count = g_hash_table_size (ptr_tracker);
+ g_print (" Left %d tracked pointers:\n", count);
+ #ifdef HAVE_BACKTRACE_SYMBOLS
+ dump_by_backtrace (ptr_tracker);
+ #else
+ g_hash_table_foreach (ptr_tracker, dump_left_ptrs_cb, &count);
+ #endif
+ }
+ g_print ("----------------------------------------------------------\n");
+ } else if (!is_at_exit) {
+ g_print ("\n----------------------------------------------------------\n");
+ g_print (" Did not track any pointers yet\n");
+ g_print ("----------------------------------------------------------\n");
+ }
+
+ G_UNLOCK (ptr_tracker);
+}
+
+#ifdef HAVE_BACKTRACE_SYMBOLS
+
+#ifdef HAVE_ELFUTILS_LIBDWFL
+static Dwfl *
+dwfl_get (gboolean reload)
+{
+ static gchar *debuginfo_path = NULL;
+ static Dwfl *dwfl = NULL;
+ static gboolean checked_for_dwfl = FALSE;
+ static GStaticMutex dwfl_mutex = G_STATIC_MUTEX_INIT;
+ static const Dwfl_Callbacks proc_callbacks = {
+ .find_debuginfo = dwfl_standard_find_debuginfo,
+ .debuginfo_path = &debuginfo_path,
+ .find_elf = dwfl_linux_proc_find_elf
+ };
+
+ g_static_mutex_lock (&dwfl_mutex);
+
+ if (checked_for_dwfl) {
+ if (!reload) {
+ g_static_mutex_unlock (&dwfl_mutex);
+ return dwfl;
+ }
+
+ dwfl_end (dwfl);
+ dwfl = NULL;
+ }
+
+ checked_for_dwfl = TRUE;
+
+ dwfl = dwfl_begin (&proc_callbacks);
+ if (!dwfl) {
+ g_static_mutex_unlock (&dwfl_mutex);
+ return NULL;
+ }
+
+ errno = 0;
+ if (dwfl_linux_proc_report (dwfl, getpid ()) != 0 || dwfl_report_end (dwfl, NULL, NULL) != 0) {
+ dwfl_end (dwfl);
+ dwfl = NULL;
+ }
+
+ g_static_mutex_unlock (&dwfl_mutex);
+
+ return dwfl;
+}
+
+struct getmodules_callback_arg
+{
+ gpointer addr;
+ const gchar *func_name;
+ const gchar *file_path;
+ gint lineno;
+};
+
+static gint
+getmodules_callback (Dwfl_Module *module,
+ gpointer *module_userdata_pointer,
+ const gchar *module_name,
+ Dwarf_Addr module_low_addr,
+ gpointer arg_voidp)
+{
+ struct getmodules_callback_arg *arg = arg_voidp;
+ Dwfl_Line *line;
+
+ arg->func_name = dwfl_module_addrname (module, (GElf_Addr) arg->addr);
+ line = dwfl_module_getsrc (module, (GElf_Addr) arg->addr);
+ if (line) {
+ arg->file_path = dwfl_lineinfo (line, NULL, &arg->lineno, NULL, NULL, NULL);
+ } else {
+ arg->file_path = NULL;
+ }
+
+ return arg->func_name ? DWARF_CB_ABORT : DWARF_CB_OK;
+}
+#endif /* HAVE_ELFUTILS_LIBDWFL */
+
+static const gchar *
+addr_lookup (gpointer addr,
+ const gchar **file_path,
+ gint *lineno,
+ const gchar *fallback)
+{
+#ifdef HAVE_ELFUTILS_LIBDWFL
+ Dwfl *dwfl = dwfl_get (FALSE);
+ struct getmodules_callback_arg arg;
+
+ if (!dwfl)
+ return NULL;
+
+ arg.addr = addr;
+ arg.func_name = NULL;
+ arg.file_path = NULL;
+ arg.lineno = -1;
+
+ dwfl_getmodules (dwfl, getmodules_callback, &arg, 0);
+
+ if (!arg.func_name && fallback && strstr (fallback, "/lib") != fallback && strstr (fallback, "/usr/lib") != fallback) {
+ dwfl = dwfl_get (TRUE);
+ if (dwfl)
+ dwfl_getmodules (dwfl, getmodules_callback, &arg, 0);
+ }
+
+ *file_path = arg.file_path;
+ *lineno = arg.lineno;
+
+ return arg.func_name;
+#else /* HAVE_ELFUTILS_LIBDWFL */
+ return NULL;
+#endif /* HAVE_ELFUTILS_LIBDWFL */
+}
+
+#endif /* HAVE_BACKTRACE_SYMBOLS */
+
+static GString *
+get_current_backtrace (void)
+{
+#ifdef HAVE_BACKTRACE_SYMBOLS
+ #define MAX_BT_DEPTH 50
+ gint nptrs, ii;
+ gpointer bt[MAX_BT_DEPTH + 1];
+ gchar **bt_syms;
+ GString *bt_str;
+
+ nptrs = backtrace (bt, MAX_BT_DEPTH + 1);
+ if (nptrs <= 2)
+ return NULL;
+
+ bt_syms = backtrace_symbols (bt, nptrs);
+ if (!bt_syms)
+ return NULL;
+
+ bt_str = g_string_new ("");
+ for (ii = 2; ii < nptrs; ii++) {
+ gint lineno = -1;
+ const gchar *file_path = NULL;
+ const gchar *str = addr_lookup (bt[ii], &file_path, &lineno, bt_syms[ii]);
+ if (!str) {
+ str = bt_syms[ii];
+ file_path = NULL;
+ lineno = -1;
+ }
+ if (!str)
+ continue;
+
+ if (bt_str->len)
+ g_string_append (bt_str, "\n\t by ");
+ g_string_append (bt_str, str);
+ if (str != bt_syms[ii])
+ g_string_append (bt_str, "()");
+
+ if (file_path && lineno > 0) {
+ const gchar *lastsep = strrchr (file_path, G_DIR_SEPARATOR);
+ g_string_append_printf (bt_str, " at %s:%d", lastsep ? lastsep + 1 : file_path, lineno);
+ }
+ }
+
+ g_free (bt_syms);
+
+ if (bt_str->len == 0) {
+ g_string_free (bt_str, TRUE);
+ bt_str = NULL;
+ } else {
+ g_string_insert (bt_str, 0, "\t at ");
+ }
+
+ return bt_str;
+
+ #undef MAX_BT_DEPTH
+#else /* HAVE_BACKTRACE_SYMBOLS */
+ return NULL;
+#endif /* HAVE_BACKTRACE_SYMBOLS */
+}
+
+static void
+dump_left_at_exit_cb (void)
+{
+ dump_tracked_ptrs (TRUE);
+
+ G_LOCK (ptr_tracker);
+ if (ptr_tracker) {
+ g_hash_table_destroy (ptr_tracker);
+ ptr_tracker = NULL;
+ }
+ G_UNLOCK (ptr_tracker);
+}
+
+/**
+ * camel_pointer_tracker_track_with_info:
+ * @ptr: pointer to add to the pointer tracker
+ * @info: info to print in tracker summary
+ *
+ * Adds pointer to the pointer tracker, with associated information,
+ * which is printed in summary of pointer tracker printed by
+ * camel_pointer_tracker_dump(). For convenience can be used
+ * camel_pointer_tracker_track(), which adds place of the caller
+ * as @info. Added pointer should be removed with pair function
+ * camel_pointer_tracker_untrack().
+ *
+ * Since: 3.6
+ **/
+void
+camel_pointer_tracker_track_with_info (gpointer ptr,
+ const gchar *info)
+{
+ struct pt_data *ptd;
+
+ g_return_if_fail (ptr != NULL);
+
+ G_LOCK (ptr_tracker);
+ if (!ptr_tracker) {
+ ptr_tracker = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_pt_data);
+ g_atexit (dump_left_at_exit_cb);
+ }
+
+ ptd = g_new0 (struct pt_data, 1);
+ ptd->ptr = ptr;
+ ptd->info = g_strdup (info);
+ ptd->backtrace = get_current_backtrace ();
+
+ g_hash_table_insert (ptr_tracker, ptr, ptd);
+
+ G_UNLOCK (ptr_tracker);
+}
+
+/**
+ * camel_pointer_tracker_untrack:
+ * @ptr: pointer to remove from the tracker
+ *
+ * Removes pointer from the pointer tracker. It's an error to try
+ * to remove pointer which was not added to the tracker by
+ * camel_pointer_tracker_track() or camel_pointer_tracker_track_with_info(),
+ * or a pointer which was already removed.
+ *
+ * Since: 3.6
+ **/
+void
+camel_pointer_tracker_untrack (gpointer ptr)
+{
+ g_return_if_fail (ptr != NULL);
+
+ G_LOCK (ptr_tracker);
+
+ if (!ptr_tracker)
+ g_printerr ("Pointer tracker not initialized, thus cannot remove %p\n", ptr);
+ else if (!g_hash_table_lookup (ptr_tracker, ptr))
+ g_printerr ("Pointer %p is not tracked\n", ptr);
+ else
+ g_hash_table_remove (ptr_tracker, ptr);
+
+ G_UNLOCK (ptr_tracker);
+}
+
+/**
+ * camel_pointer_tracker_dump:
+ *
+ * Prints information about currently stored pointers
+ * in the pointer tracker. This is called automatically
+ * on application exit if camel_pointer_tracker_track() or
+ * camel_pointer_tracker_track_with_info() was called.
+ *
+ * Note: If the library is configured with --enable-backtraces,
+ * then also backtraces where the pointer was added is printed
+ * in the summary.
+ *
+ * Since: 3.6
+ **/
+void
+camel_pointer_tracker_dump (void)
+{
+ dump_tracked_ptrs (FALSE);
+}
diff --git a/camel/camel-debug.h b/camel/camel-debug.h
index c85bbcf..4bb097a 100644
--- a/camel/camel-debug.h
+++ b/camel/camel-debug.h
@@ -79,6 +79,29 @@ void camel_debug_end (void);
} \
} G_STMT_END
+/**
+ * camel_pointer_tracker_track:
+ * @ptr: pointer to add to pointer tracker
+ *
+ * Adds pointer 'ptr' to pointer tracker. Usual use case is to add object
+ * to the tracker in GObject::init and remove it from tracker within
+ * GObject::finalize. Since the tracker's functions are called, the application
+ * prints summary of the pointers on console on exit. If everything gone right
+ * then it prints message about all tracked pointers were removed. Otherwise
+ * it prints summary of left pointers in the tracker. Added pointer should
+ * be removed with pair function camel_pointer_tracker_untrack().
+ *
+ * See camel_pointer_tracker_dump(), camel_pointer_tracker_track_with_info().
+ *
+ * Since: 3.6
+ **/
+#define camel_pointer_tracker_track(ptr) \
+ (camel_pointer_tracker_track_with_info ((ptr), G_STRFUNC))
+
+void camel_pointer_tracker_track_with_info (gpointer ptr, const gchar *info);
+void camel_pointer_tracker_untrack (gpointer ptr);
+void camel_pointer_tracker_dump (void);
+
G_END_DECLS
#endif /* CAMEL_DEBUG_H */
diff --git a/configure.ac b/configure.ac
index cee40b3..a55a5d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -558,7 +558,7 @@ LIBS="$save_LIBS"
AC_ARG_ENABLE([backtraces],
[AS_HELP_STRING([--enable-backtraces],
- [enable backtraces for e_pointer_tracker (default=no)])],
+ [enable backtraces for camel_pointer_tracker (default=no)])],
[enable_backtraces=$enableval], [enable_backtraces=no])
if test "x$enable_backtraces" = xyes; then
diff --git a/libedataserver/Makefile.am b/libedataserver/Makefile.am
index 4c0d9e5..72f689a 100644
--- a/libedataserver/Makefile.am
+++ b/libedataserver/Makefile.am
@@ -105,8 +105,7 @@ libedataserver_1_2_la_LIBADD = \
$(GIO_UNIX_LIBS) \
$(ICONV_LIBS) \
$(SOCKET_LIBS) \
- $(SOUP_LIBS) \
- $(LIBDWFL_LIBS)
+ $(SOUP_LIBS)
libedataserver_1_2_la_LDFLAGS = \
-version-info $(LIBEDATASERVER_CURRENT):$(LIBEDATASERVER_REVISION):$(LIBEDATASERVER_AGE) $(NO_UNDEFINED) \
diff --git a/libedataserver/e-data-server-util.c b/libedataserver/e-data-server-util.c
index e18831d..3aca9e8 100644
--- a/libedataserver/e-data-server-util.c
+++ b/libedataserver/e-data-server-util.c
@@ -26,14 +26,6 @@
#include <time.h>
#include <unistd.h>
-#ifdef HAVE_BACKTRACE_SYMBOLS
-#include <execinfo.h>
-#ifdef HAVE_ELFUTILS_LIBDWFL
-#include <elfutils/libdwfl.h>
-#include <errno.h>
-#endif
-#endif
-
#ifdef G_OS_WIN32
#include <mbstring.h>
#endif
@@ -1548,397 +1540,3 @@ e_data_server_util_get_dbus_call_timeout (void)
{
return default_dbus_timeout;
}
-
-G_LOCK_DEFINE_STATIC (ptr_tracker);
-static GHashTable *ptr_tracker = NULL;
-
-struct pt_data {
- gpointer ptr;
- gchar *info;
- GString *backtrace;
-};
-
-static void
-free_pt_data (gpointer ptr)
-{
- struct pt_data *ptd = ptr;
-
- if (!ptd)
- return;
-
- g_free (ptd->info);
- if (ptd->backtrace)
- g_string_free (ptd->backtrace, TRUE);
- g_free (ptd);
-}
-
-static void
-dump_left_ptrs_cb (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint *left = user_data;
- struct pt_data *ptd = value;
- gboolean have_info = ptd && ptd->info;
- gboolean have_bt = ptd && ptd->backtrace && ptd->backtrace->str && *ptd->backtrace->str;
-
- *left = (*left) - 1;
- g_print (" %p %s%s%s%s%s%s\n", key, have_info ? "(" : "", have_info ? ptd->info : "", have_info ? ")" : "", have_bt ? "\n" : "", have_bt ? ptd->backtrace->str : "", have_bt && *left > 0 ? "\n" : "");
-}
-
-#ifdef HAVE_BACKTRACE_SYMBOLS
-static guint
-by_backtrace_hash (gconstpointer ptr)
-{
- const struct pt_data *ptd = ptr;
-
- if (!ptd || !ptd->backtrace)
- return 0;
-
- return g_str_hash (ptd->backtrace->str);
-}
-
-static gboolean
-by_backtrace_equal (gconstpointer ptr1,
- gconstpointer ptr2)
-{
- const struct pt_data *ptd1 = ptr1, *ptd2 = ptr2;
-
- if ((!ptd1 || !ptd1->backtrace) && (!ptd2 || !ptd2->backtrace))
- return TRUE;
-
- return ptd1 && ptd1->backtrace && ptd2 && ptd2->backtrace && g_str_equal (ptd1->backtrace->str, ptd2->backtrace->str);
-}
-
-static void
-dump_by_backtrace_cb (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint *left = user_data;
- struct pt_data *ptd = key;
- guint count = GPOINTER_TO_UINT (value);
-
- if (count == 1) {
- dump_left_ptrs_cb (ptd->ptr, ptd, left);
- } else {
- gboolean have_info = ptd && ptd->info;
- gboolean have_bt = ptd && ptd->backtrace && ptd->backtrace->str && *ptd->backtrace->str;
-
- *left = (*left) - 1;
-
- g_print (" %d x %s%s%s%s%s%s\n", count, have_info ? "(" : "", have_info ? ptd->info : "", have_info ? ")" : "", have_bt ? "\n" : "", have_bt ? ptd->backtrace->str : "", have_bt && *left > 0 ? "\n" : "");
- }
-}
-
-static void
-dump_by_backtrace (GHashTable *ptrs)
-{
- GHashTable *by_bt = g_hash_table_new (by_backtrace_hash, by_backtrace_equal);
- GHashTableIter iter;
- gpointer key, value;
- struct ptr_data *ptd;
- guint count;
-
- g_hash_table_iter_init (&iter, ptrs);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- guint cnt;
-
- ptd = value;
- if (!ptd)
- continue;
-
- cnt = GPOINTER_TO_UINT (g_hash_table_lookup (by_bt, ptd));
- cnt++;
-
- g_hash_table_insert (by_bt, ptd, GUINT_TO_POINTER (cnt));
- }
-
- count = g_hash_table_size (by_bt);
- g_hash_table_foreach (by_bt, dump_by_backtrace_cb, &count);
- g_hash_table_destroy (by_bt);
-}
-#endif /* HAVE_BACKTRACE_SYMBOLS */
-
-static void
-dump_tracked_ptrs (gboolean is_at_exit)
-{
- G_LOCK (ptr_tracker);
-
- if (ptr_tracker) {
- g_print ("\n----------------------------------------------------------\n");
- if (g_hash_table_size (ptr_tracker) == 0) {
- g_print (" All tracked pointers were properly removed\n");
- } else {
- guint count = g_hash_table_size (ptr_tracker);
- g_print (" Left %d tracked pointers:\n", count);
- #ifdef HAVE_BACKTRACE_SYMBOLS
- dump_by_backtrace (ptr_tracker);
- #else
- g_hash_table_foreach (ptr_tracker, dump_left_ptrs_cb, &count);
- #endif
- }
- g_print ("----------------------------------------------------------\n");
- } else if (!is_at_exit) {
- g_print ("\n----------------------------------------------------------\n");
- g_print (" Did not track any pointers yet\n");
- g_print ("----------------------------------------------------------\n");
- }
-
- G_UNLOCK (ptr_tracker);
-}
-
-#ifdef HAVE_BACKTRACE_SYMBOLS
-
-#ifdef HAVE_ELFUTILS_LIBDWFL
-static Dwfl *
-dwfl_get (gboolean reload)
-{
- static gchar *debuginfo_path = NULL;
- static Dwfl *dwfl = NULL;
- static gboolean checked_for_dwfl = FALSE;
- static GStaticMutex dwfl_mutex = G_STATIC_MUTEX_INIT;
- static const Dwfl_Callbacks proc_callbacks = {
- .find_debuginfo = dwfl_standard_find_debuginfo,
- .debuginfo_path = &debuginfo_path,
- .find_elf = dwfl_linux_proc_find_elf
- };
-
- g_static_mutex_lock (&dwfl_mutex);
-
- if (checked_for_dwfl) {
- if (!reload) {
- g_static_mutex_unlock (&dwfl_mutex);
- return dwfl;
- }
-
- dwfl_end (dwfl);
- dwfl = NULL;
- }
-
- checked_for_dwfl = TRUE;
-
- dwfl = dwfl_begin (&proc_callbacks);
- if (!dwfl) {
- g_static_mutex_unlock (&dwfl_mutex);
- return NULL;
- }
-
- errno = 0;
- if (dwfl_linux_proc_report (dwfl, getpid ()) != 0 || dwfl_report_end (dwfl, NULL, NULL) != 0) {
- dwfl_end (dwfl);
- dwfl = NULL;
- }
-
- g_static_mutex_unlock (&dwfl_mutex);
-
- return dwfl;
-}
-
-struct getmodules_callback_arg
-{
- gpointer addr;
- const gchar *func_name;
- const gchar *file_path;
- gint lineno;
-};
-
-static gint
-getmodules_callback (Dwfl_Module *module,
- gpointer *module_userdata_pointer,
- const gchar *module_name,
- Dwarf_Addr module_low_addr,
- gpointer arg_voidp)
-{
- struct getmodules_callback_arg *arg = arg_voidp;
- Dwfl_Line *line;
-
- arg->func_name = dwfl_module_addrname (module, (GElf_Addr) arg->addr);
- line = dwfl_module_getsrc (module, (GElf_Addr) arg->addr);
- if (line) {
- arg->file_path = dwfl_lineinfo (line, NULL, &arg->lineno, NULL, NULL, NULL);
- } else {
- arg->file_path = NULL;
- }
-
- return arg->func_name ? DWARF_CB_ABORT : DWARF_CB_OK;
-}
-#endif /* HAVE_ELFUTILS_LIBDWFL */
-
-static const gchar *
-addr_lookup (gpointer addr,
- const gchar **file_path,
- gint *lineno,
- const gchar *fallback)
-{
-#ifdef HAVE_ELFUTILS_LIBDWFL
- Dwfl *dwfl = dwfl_get (FALSE);
- struct getmodules_callback_arg arg;
-
- if (!dwfl)
- return NULL;
-
- arg.addr = addr;
- arg.func_name = NULL;
- arg.file_path = NULL;
- arg.lineno = -1;
-
- dwfl_getmodules (dwfl, getmodules_callback, &arg, 0);
-
- if (!arg.func_name && fallback && strstr (fallback, "/lib") != fallback && strstr (fallback, "/usr/lib") != fallback) {
- dwfl = dwfl_get (TRUE);
- if (dwfl)
- dwfl_getmodules (dwfl, getmodules_callback, &arg, 0);
- }
-
- *file_path = arg.file_path;
- *lineno = arg.lineno;
-
- return arg.func_name;
-#else /* HAVE_ELFUTILS_LIBDWFL */
- return NULL;
-#endif /* HAVE_ELFUTILS_LIBDWFL */
-}
-
-#endif /* HAVE_BACKTRACE_SYMBOLS */
-
-static GString *
-get_current_backtrace (void)
-{
-#ifdef HAVE_BACKTRACE_SYMBOLS
- #define MAX_BT_DEPTH 50
- gint nptrs, ii;
- gpointer bt[MAX_BT_DEPTH + 1];
- gchar **bt_syms;
- GString *bt_str;
-
- nptrs = backtrace (bt, MAX_BT_DEPTH + 1);
- if (nptrs <= 2)
- return NULL;
-
- bt_syms = backtrace_symbols (bt, nptrs);
- if (!bt_syms)
- return NULL;
-
- bt_str = g_string_new ("");
- for (ii = 2; ii < nptrs; ii++) {
- gint lineno = -1;
- const gchar *file_path = NULL;
- const gchar *str = addr_lookup (bt[ii], &file_path, &lineno, bt_syms[ii]);
- if (!str) {
- str = bt_syms[ii];
- file_path = NULL;
- lineno = -1;
- }
- if (!str)
- continue;
-
- if (bt_str->len)
- g_string_append (bt_str, "\n\t by ");
- g_string_append (bt_str, str);
- if (str != bt_syms[ii])
- g_string_append (bt_str, "()");
-
- if (file_path && lineno > 0) {
- const gchar *lastsep = strrchr (file_path, G_DIR_SEPARATOR);
- g_string_append_printf (bt_str, " at %s:%d", lastsep ? lastsep + 1 : file_path, lineno);
- }
- }
-
- g_free (bt_syms);
-
- if (bt_str->len == 0) {
- g_string_free (bt_str, TRUE);
- bt_str = NULL;
- } else {
- g_string_insert (bt_str, 0, "\t at ");
- }
-
- return bt_str;
-
- #undef MAX_BT_DEPTH
-#else /* HAVE_BACKTRACE_SYMBOLS */
- return NULL;
-#endif /* HAVE_BACKTRACE_SYMBOLS */
-}
-
-static void
-dump_left_at_exit_cb (void)
-{
- dump_tracked_ptrs (TRUE);
-
- G_LOCK (ptr_tracker);
- if (ptr_tracker) {
- g_hash_table_destroy (ptr_tracker);
- ptr_tracker = NULL;
- }
- G_UNLOCK (ptr_tracker);
-}
-
-/**
- * e_pointer_tracker_track_with_info:
- *
- * FIXME: Document me.
- *
- * Since: 3.2
- **/
-void
-e_pointer_tracker_track_with_info (gpointer ptr,
- const gchar *info)
-{
- struct pt_data *ptd;
-
- g_return_if_fail (ptr != NULL);
-
- G_LOCK (ptr_tracker);
- if (!ptr_tracker) {
- ptr_tracker = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_pt_data);
- g_atexit (dump_left_at_exit_cb);
- }
-
- ptd = g_new0 (struct pt_data, 1);
- ptd->ptr = ptr;
- ptd->info = g_strdup (info);
- ptd->backtrace = get_current_backtrace ();
-
- g_hash_table_insert (ptr_tracker, ptr, ptd);
-
- G_UNLOCK (ptr_tracker);
-}
-
-/**
- * e_pointer_tracker_untrack:
- *
- * FIXME: Document me.
- *
- * Since: 3.2
- **/
-void
-e_pointer_tracker_untrack (gpointer ptr)
-{
- g_return_if_fail (ptr != NULL);
-
- G_LOCK (ptr_tracker);
-
- if (!ptr_tracker)
- g_printerr ("Pointer tracker not initialized, thus cannot remove %p\n", ptr);
- else if (!g_hash_table_lookup (ptr_tracker, ptr))
- g_printerr ("Pointer %p is not tracked\n", ptr);
- else
- g_hash_table_remove (ptr_tracker, ptr);
-
- G_UNLOCK (ptr_tracker);
-}
-
-/**
- * e_pointer_tracker_dump:
- *
- * FIXME: Document me.
- *
- * Since: 3.2
- **/
-void
-e_pointer_tracker_dump (void)
-{
- dump_tracked_ptrs (FALSE);
-}
diff --git a/libedataserver/e-data-server-util.h b/libedataserver/e-data-server-util.h
index 371a415..24e26a1 100644
--- a/libedataserver/e-data-server-util.h
+++ b/libedataserver/e-data-server-util.h
@@ -123,20 +123,6 @@ gint e_data_server_util_get_dbus_call_timeout
void e_data_server_util_set_dbus_call_timeout
(gint timeout_msec);
-/**
- * e_pointer_tracker_track:
- *
- * FIXME: Document me.
- *
- * Since: 3.2
- **/
-#define e_pointer_tracker_track(ptr) \
- (e_pointer_tracker_track_with_info ((ptr), G_STRFUNC))
-
-void e_pointer_tracker_track_with_info (gpointer ptr, const gchar *info);
-void e_pointer_tracker_untrack (gpointer ptr);
-void e_pointer_tracker_dump (void);
-
G_END_DECLS
#endif /* E_DATA_SERVER_UTIL_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]