mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-23 06:26:23 +00:00
validate: launcher: Add a way to retrieve trace without coredumpctl
Simply spnning on segfaults (like gst-launch) and catch that in the launcher to transform the timeout into a segfault and grab a gdb backtrace
This commit is contained in:
parent
21e23c72fc
commit
72995d5bbe
6 changed files with 119 additions and 19 deletions
|
@ -20,11 +20,23 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include<math.h>
|
#include "config.h"
|
||||||
#include<ctype.h>
|
|
||||||
#include<stdio.h>
|
#include <math.h>
|
||||||
#include<string.h>
|
#include <ctype.h>
|
||||||
#include<stdlib.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
#include <glib-unix.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "gst-validate-utils.h"
|
#include "gst-validate-utils.h"
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
@ -821,3 +833,76 @@ gst_validate_object_set_property (GstValidateReporter * reporter,
|
||||||
g_value_reset (&nvalue);
|
g_value_reset (&nvalue);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
static void
|
||||||
|
fault_restore (void)
|
||||||
|
{
|
||||||
|
struct sigaction action;
|
||||||
|
|
||||||
|
memset (&action, 0, sizeof (action));
|
||||||
|
action.sa_handler = SIG_DFL;
|
||||||
|
|
||||||
|
sigaction (SIGSEGV, &action, NULL);
|
||||||
|
sigaction (SIGQUIT, &action, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fault_spin (void)
|
||||||
|
{
|
||||||
|
int spinning = TRUE;
|
||||||
|
|
||||||
|
g_on_error_stack_trace ("GstValidate");
|
||||||
|
|
||||||
|
wait (NULL);
|
||||||
|
|
||||||
|
g_printerr ("Please run 'gdb <process-name> %d' to "
|
||||||
|
"continue debugging, Ctrl-C to quit, or Ctrl-\\ to dump core.\n",
|
||||||
|
(gint) getpid ());
|
||||||
|
|
||||||
|
while (spinning)
|
||||||
|
g_usleep (1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fault_handler_sighandler (int signum)
|
||||||
|
{
|
||||||
|
fault_restore ();
|
||||||
|
|
||||||
|
/* printf is used instead of g_print(), since it's less likely to
|
||||||
|
* deadlock */
|
||||||
|
switch (signum) {
|
||||||
|
case SIGSEGV:
|
||||||
|
g_printerr ("<Caught SIGNAL: SIGSEGV>\n");
|
||||||
|
break;
|
||||||
|
case SIGQUIT:
|
||||||
|
g_print ("<Caught SIGNAL: SIGQUIT>\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_printerr ("<Caught SIGNAL: %d>\n", signum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fault_spin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fault_setup (void)
|
||||||
|
{
|
||||||
|
struct sigaction action;
|
||||||
|
|
||||||
|
memset (&action, 0, sizeof (action));
|
||||||
|
action.sa_handler = fault_handler_sighandler;
|
||||||
|
|
||||||
|
sigaction (SIGSEGV, &action, NULL);
|
||||||
|
sigaction (SIGQUIT, &action, NULL);
|
||||||
|
}
|
||||||
|
#endif /* G_OS_UNIX */
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_validate_spin_on_fault_signals (void)
|
||||||
|
{
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
fault_setup ();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -64,4 +64,7 @@ GstValidateActionReturn gst_validate_object_set_property (GstValidateReporter *
|
||||||
const GValue * value,
|
const GValue * value,
|
||||||
gboolean optional);
|
gboolean optional);
|
||||||
|
|
||||||
|
GST_VALIDATE_API
|
||||||
|
void gst_validate_spin_on_fault_signals (void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -232,6 +232,7 @@ class Test(Loggable):
|
||||||
self.add_env_variable("DISPLAY")
|
self.add_env_variable("DISPLAY")
|
||||||
|
|
||||||
def add_stack_trace_to_logfile(self):
|
def add_stack_trace_to_logfile(self):
|
||||||
|
self.debug("Adding stack trace")
|
||||||
trace_gatherer = BackTraceGenerator.get_default()
|
trace_gatherer = BackTraceGenerator.get_default()
|
||||||
stack_trace = trace_gatherer.get_trace(self)
|
stack_trace = trace_gatherer.get_trace(self)
|
||||||
|
|
||||||
|
@ -241,11 +242,13 @@ class Test(Loggable):
|
||||||
info = "\n\n== Stack trace: == \n%s" % stack_trace
|
info = "\n\n== Stack trace: == \n%s" % stack_trace
|
||||||
if self.options.redirect_logs:
|
if self.options.redirect_logs:
|
||||||
print(info)
|
print(info)
|
||||||
elif self.options.xunit_file:
|
return
|
||||||
|
|
||||||
|
if self.options.xunit_file:
|
||||||
self.stack_trace = stack_trace
|
self.stack_trace = stack_trace
|
||||||
else:
|
|
||||||
with open(self.logfile, 'a') as f:
|
with open(self.logfile, 'a') as f:
|
||||||
f.write(info)
|
f.write(info)
|
||||||
|
|
||||||
def set_result(self, result, message="", error=""):
|
def set_result(self, result, message="", error=""):
|
||||||
self.debug("Setting result: %s (message: %s, error: %s)" % (result,
|
self.debug("Setting result: %s (message: %s, error: %s)" % (result,
|
||||||
|
@ -638,12 +641,8 @@ class GstValidateListener(socketserver.BaseRequestHandler):
|
||||||
class GstValidateTest(Test):
|
class GstValidateTest(Test):
|
||||||
|
|
||||||
""" A class representing a particular test. """
|
""" A class representing a particular test. """
|
||||||
findpos_regex = re.compile(
|
|
||||||
'.*position.*(\d+):(\d+):(\d+).(\d+).*duration.*(\d+):(\d+):(\d+).(\d+)')
|
|
||||||
findlastseek_regex = re.compile(
|
|
||||||
'seeking to.*(\d+):(\d+):(\d+).(\d+).*stop.*(\d+):(\d+):(\d+).(\d+).*rate.*(\d+)\.(\d+)')
|
|
||||||
|
|
||||||
HARD_TIMEOUT_FACTOR = 5
|
HARD_TIMEOUT_FACTOR = 5
|
||||||
|
fault_sig_regex = re.compile("<Caught SIGNAL: .*>")
|
||||||
|
|
||||||
def __init__(self, application_name, classname,
|
def __init__(self, application_name, classname,
|
||||||
options, reporter, duration=0,
|
options, reporter, duration=0,
|
||||||
|
@ -908,11 +907,16 @@ class GstValidateTest(Test):
|
||||||
msg = ""
|
msg = ""
|
||||||
result = Result.PASSED
|
result = Result.PASSED
|
||||||
if self.result == Result.TIMEOUT:
|
if self.result == Result.TIMEOUT:
|
||||||
if expected_timeout:
|
with open(self.logfile) as f:
|
||||||
not_found_expected_failures.remove(expected_timeout)
|
signal_fault_info = self.fault_sig_regex.findall(f.read())
|
||||||
result, msg = self.check_expected_timeout(expected_timeout)
|
if signal_fault_info:
|
||||||
else:
|
result = Result.FAILED
|
||||||
return
|
msg = signal_fault_info[0]
|
||||||
|
elif expected_timeout:
|
||||||
|
not_found_expected_failures.remove(expected_timeout)
|
||||||
|
result, msg = self.check_expected_timeout(expected_timeout)
|
||||||
|
else:
|
||||||
|
return
|
||||||
elif self.process.returncode in COREDUMP_SIGNALS:
|
elif self.process.returncode in COREDUMP_SIGNALS:
|
||||||
result = Result.FAILED
|
result = Result.FAILED
|
||||||
msg = "Application segfaulted "
|
msg = "Application segfaulted "
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <gst/validate/media-descriptor-writer.h>
|
#include <gst/validate/media-descriptor-writer.h>
|
||||||
#include <gst/validate/media-descriptor-parser.h>
|
#include <gst/validate/media-descriptor-parser.h>
|
||||||
#include <gst/validate/media-descriptor.h>
|
#include <gst/validate/media-descriptor.h>
|
||||||
|
#include <gst/validate/gst-validate-utils.h>
|
||||||
#include <gst/pbutils/encoding-profile.h>
|
#include <gst/pbutils/encoding-profile.h>
|
||||||
#include <locale.h> /* for LC_ALL */
|
#include <locale.h> /* for LC_ALL */
|
||||||
|
|
||||||
|
@ -102,6 +103,8 @@ main (int argc, gchar ** argv)
|
||||||
}
|
}
|
||||||
g_option_context_free (ctx);
|
g_option_context_free (ctx);
|
||||||
|
|
||||||
|
gst_validate_spin_on_fault_signals ();
|
||||||
|
|
||||||
runner = gst_validate_runner_new ();
|
runner = gst_validate_runner_new ();
|
||||||
|
|
||||||
if (expected_file) {
|
if (expected_file) {
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/validate/gst-validate-utils.h>
|
||||||
#include <gst/validate/validate.h>
|
#include <gst/validate/validate.h>
|
||||||
#include <gst/pbutils/encoding-profile.h>
|
#include <gst/pbutils/encoding-profile.h>
|
||||||
|
|
||||||
|
@ -836,6 +837,8 @@ main (int argc, gchar ** argv)
|
||||||
g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
|
g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
gst_validate_spin_on_fault_signals ();
|
||||||
|
|
||||||
monitor =
|
monitor =
|
||||||
gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline), runner,
|
gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline), runner,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
|
@ -457,6 +457,8 @@ main (int argc, gchar ** argv)
|
||||||
g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
|
g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
gst_validate_spin_on_fault_signals ();
|
||||||
|
|
||||||
if (_is_playbin_pipeline (argc - 1, argv + 1)) {
|
if (_is_playbin_pipeline (argc - 1, argv + 1)) {
|
||||||
_register_playbin_actions ();
|
_register_playbin_actions ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue