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_FUNCTION
GstLogFunction
GstStackTraceFlags
gst_debug_log
gst_debug_log_valist
gst_debug_message_get

View file

@ -2646,7 +2646,7 @@ append_debug_info (GString * trace, Dwfl * dwfl, const void *ip)
#endif /* HAVE_DW */
static gchar *
generate_unwind_trace (void)
generate_unwind_trace (GstStackTraceFlags flags)
{
unw_context_t uc;
unw_cursor_t cursor;
@ -2654,14 +2654,14 @@ generate_unwind_trace (void)
GString *trace = g_string_new (NULL);
#ifdef HAVE_DW
Dwfl *dwfl;
Dwfl *dwfl = NULL;
Dwfl_Callbacks callbacks = {
.find_elf = dwfl_linux_proc_find_elf,
.find_debuginfo = dwfl_standard_find_debuginfo,
};
dwfl = dwfl_begin (&callbacks);
if ((flags & GST_STACK_TRACE_SHOW_FULL))
dwfl = dwfl_begin (&callbacks);
#endif /* HAVE_DW */
unw_getcontext (&uc);
@ -2691,7 +2691,8 @@ generate_unwind_trace (void)
}
#ifdef HAVE_DW
dwfl_end (dwfl);
if (dwfl)
dwfl_end (dwfl);
#endif
return g_string_free (trace, FALSE);
@ -2725,26 +2726,35 @@ generate_backtrace_trace (void)
/**
* 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
* is returned.
*
* Since: 1.12
*/
gchar *
gst_debug_get_stack_trace (void)
gst_debug_get_stack_trace (GstStackTraceFlags flags)
{
gchar *trace = NULL;
#ifdef HAVE_BACKTRACE
gboolean have_backtrace = TRUE;
#else
gboolean have_backtrace = FALSE;
#endif
#ifdef HAVE_UNWIND
trace = generate_unwind_trace ();
if (trace)
return trace;
if ((flags & GST_STACK_TRACE_SHOW_FULL) || !have_backtrace)
trace = generate_unwind_trace (flags);
#endif /* HAVE_UNWIND */
#ifdef HAVE_BACKTRACE
trace = generate_backtrace_trace ();
#endif /* HAVE_BACKTRACE */
if (trace)
return trace;
else if (have_backtrace)
return generate_backtrace_trace ();
return trace;
return NULL;
}
/**
@ -2756,7 +2766,7 @@ gst_debug_get_stack_trace (void)
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)
g_print ("%s\n", trace);

View file

@ -175,6 +175,15 @@ typedef enum {
GST_DEBUG_UNDERLINE = 0x0200
} 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:
* @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);
gchar * gst_debug_get_stack_trace (void);
gchar * gst_debug_get_stack_trace (GstStackTraceFlags flags);
G_END_DECLS

View file

@ -221,7 +221,7 @@ handle_object_created (GstLeaksTracer * self, gpointer object, GType type,
GST_OBJECT_LOCK (self);
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);
@ -264,7 +264,7 @@ gst_leaks_tracer_init (GstLeaksTracer * self)
gchar *trace;
/* 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) {
self->log_stack_trace = TRUE;
g_free (trace);