info: Add a 'flags' parametter to gst_debug_get_stack_trace

This is an API break but that API has not been released yet.

We are passing a flag rather than a simple boolean as we can imagine
to implement more features in the future for example to retrieve a
stack trace for all the threads, etc..

Retrieving source file and line numbers is pretty
expensive while getting a stack trace, this new argument
allows the user to decide to retrieve a backtrace
without those infos instead which is much faster.

For example running $ GST_LEAKS_TRACER_STACK_TRACE=1 GST_DEBUG=GST_TRACER:7 \
GST_TRACERS=leaks time gst-launch-1.0 videotestsrc num-buffers=1 ! fakesink:

* With simple stack traces:

    0.04s user 0.02s system 99% cpu 0.060 total

* With full stack traces:

    0.66s user 0.23s system 96% cpu 0.926 total

https://bugzilla.gnome.org/show_bug.cgi?id=775423
This commit is contained in:
Thibault Saunier 2016-11-30 15:10:48 -03:00
parent 6b73bf38d1
commit 33616d47be
4 changed files with 37 additions and 17 deletions

View file

@ -1328,6 +1328,7 @@ GST_STR_NULL
GST_DEBUG_PAD_NAME GST_DEBUG_PAD_NAME
GST_FUNCTION GST_FUNCTION
GstLogFunction GstLogFunction
GstStackTraceFlags
gst_debug_log gst_debug_log
gst_debug_log_valist gst_debug_log_valist
gst_debug_message_get gst_debug_message_get

View file

@ -2646,7 +2646,7 @@ append_debug_info (GString * trace, Dwfl * dwfl, const void *ip)
#endif /* HAVE_DW */ #endif /* HAVE_DW */
static gchar * static gchar *
generate_unwind_trace (void) generate_unwind_trace (GstStackTraceFlags flags)
{ {
unw_context_t uc; unw_context_t uc;
unw_cursor_t cursor; unw_cursor_t cursor;
@ -2654,14 +2654,14 @@ generate_unwind_trace (void)
GString *trace = g_string_new (NULL); GString *trace = g_string_new (NULL);
#ifdef HAVE_DW #ifdef HAVE_DW
Dwfl *dwfl; Dwfl *dwfl = NULL;
Dwfl_Callbacks callbacks = { Dwfl_Callbacks callbacks = {
.find_elf = dwfl_linux_proc_find_elf, .find_elf = dwfl_linux_proc_find_elf,
.find_debuginfo = dwfl_standard_find_debuginfo, .find_debuginfo = dwfl_standard_find_debuginfo,
}; };
dwfl = dwfl_begin (&callbacks); if ((flags & GST_STACK_TRACE_SHOW_FULL))
dwfl = dwfl_begin (&callbacks);
#endif /* HAVE_DW */ #endif /* HAVE_DW */
unw_getcontext (&uc); unw_getcontext (&uc);
@ -2691,7 +2691,8 @@ generate_unwind_trace (void)
} }
#ifdef HAVE_DW #ifdef HAVE_DW
dwfl_end (dwfl); if (dwfl)
dwfl_end (dwfl);
#endif #endif
return g_string_free (trace, FALSE); return g_string_free (trace, FALSE);
@ -2725,26 +2726,35 @@ generate_backtrace_trace (void)
/** /**
* gst_debug_get_stack_trace: * gst_debug_get_stack_trace:
* @flags: A set of #GstStackTraceFlags to determine how the stack
* trace should look like. Pass 0 to retrieve a minimal backtrace.
* *
* If libunwind or glibc backtrace are present, a stack trace * If libunwind or glibc backtrace are present, a stack trace
* is returned. * is returned.
*
* Since: 1.12
*/ */
gchar * gchar *
gst_debug_get_stack_trace (void) gst_debug_get_stack_trace (GstStackTraceFlags flags)
{ {
gchar *trace = NULL; gchar *trace = NULL;
#ifdef HAVE_BACKTRACE
gboolean have_backtrace = TRUE;
#else
gboolean have_backtrace = FALSE;
#endif
#ifdef HAVE_UNWIND #ifdef HAVE_UNWIND
trace = generate_unwind_trace (); if ((flags & GST_STACK_TRACE_SHOW_FULL) || !have_backtrace)
if (trace) trace = generate_unwind_trace (flags);
return trace;
#endif /* HAVE_UNWIND */ #endif /* HAVE_UNWIND */
#ifdef HAVE_BACKTRACE if (trace)
trace = generate_backtrace_trace (); return trace;
#endif /* HAVE_BACKTRACE */ else if (have_backtrace)
return generate_backtrace_trace ();
return trace; return NULL;
} }
/** /**
@ -2756,7 +2766,7 @@ gst_debug_get_stack_trace (void)
void void
gst_debug_print_stack_trace (void) gst_debug_print_stack_trace (void)
{ {
gchar *trace = gst_debug_get_stack_trace (); gchar *trace = gst_debug_get_stack_trace (GST_STACK_TRACE_SHOW_FULL);
if (trace) if (trace)
g_print ("%s\n", trace); g_print ("%s\n", trace);

View file

@ -175,6 +175,15 @@ typedef enum {
GST_DEBUG_UNDERLINE = 0x0200 GST_DEBUG_UNDERLINE = 0x0200
} GstDebugColorFlags; } GstDebugColorFlags;
/**
* GstStackTraceFlags:
* @GST_STACK_TRACE_SHOW_FULL: Try to retrieve as much information as
* possible when getting the stack trace
*/
typedef enum {
GST_STACK_TRACE_SHOW_FULL = 1 << 0
} GstStackTraceFlags;
/** /**
* GstDebugColorMode: * GstDebugColorMode:
* @GST_DEBUG_COLOR_MODE_OFF: Do not use colors in logs. * @GST_DEBUG_COLOR_MODE_OFF: Do not use colors in logs.
@ -1570,7 +1579,7 @@ GST_TRACE (const char *format, ...)
void gst_debug_print_stack_trace (void); void gst_debug_print_stack_trace (void);
gchar * gst_debug_get_stack_trace (void); gchar * gst_debug_get_stack_trace (GstStackTraceFlags flags);
G_END_DECLS G_END_DECLS

View file

@ -221,7 +221,7 @@ handle_object_created (GstLeaksTracer * self, gpointer object, GType type,
GST_OBJECT_LOCK (self); GST_OBJECT_LOCK (self);
if (self->log_stack_trace) { if (self->log_stack_trace) {
trace = gst_debug_get_stack_trace (); trace = gst_debug_get_stack_trace (GST_STACK_TRACE_SHOW_FULL);
} }
g_hash_table_insert (self->objects, object, trace); g_hash_table_insert (self->objects, object, trace);
@ -264,7 +264,7 @@ gst_leaks_tracer_init (GstLeaksTracer * self)
gchar *trace; gchar *trace;
/* Test if we can retrieve backtrace */ /* Test if we can retrieve backtrace */
trace = gst_debug_get_stack_trace (); trace = gst_debug_get_stack_trace (GST_STACK_TRACE_SHOW_FULL);
if (trace) { if (trace) {
self->log_stack_trace = TRUE; self->log_stack_trace = TRUE;
g_free (trace); g_free (trace);