validate: launcher: Add a way to retrieve trace without coredumpctl
authorThibault Saunier <tsaunier@igalia.com>
Fri, 7 Dec 2018 12:03:24 +0000 (09:03 -0300)
committerThibault Saunier <tsaunier@igalia.com>
Fri, 7 Dec 2018 12:06:50 +0000 (09:06 -0300)
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

validate/gst/validate/gst-validate-utils.c
validate/gst/validate/gst-validate-utils.h
validate/launcher/baseclasses.py
validate/tools/gst-validate-media-check.c
validate/tools/gst-validate-transcoding.c
validate/tools/gst-validate.c

index 5f75841..af8486b 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-#include<math.h>
-#include<ctype.h>
-#include<stdio.h>
-#include<string.h>
-#include<stdlib.h>
+#include "config.h"
+
+#include <math.h>
+#include <ctype.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/gst.h>
@@ -821,3 +833,76 @@ gst_validate_object_set_property (GstValidateReporter * reporter,
   g_value_reset (&nvalue);
   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
+}
index 16d92e5..385fee8 100644 (file)
@@ -64,4 +64,7 @@ GstValidateActionReturn gst_validate_object_set_property (GstValidateReporter *
                                                           const GValue * value,
                                                           gboolean optional);
 
+GST_VALIDATE_API
+void gst_validate_spin_on_fault_signals (void);
+
 #endif
index 269c12e..4eab026 100644 (file)
@@ -232,6 +232,7 @@ class Test(Loggable):
         self.add_env_variable("DISPLAY")
 
     def add_stack_trace_to_logfile(self):
+        self.debug("Adding stack trace")
         trace_gatherer = BackTraceGenerator.get_default()
         stack_trace = trace_gatherer.get_trace(self)
 
@@ -241,11 +242,13 @@ class Test(Loggable):
         info = "\n\n== Stack trace: == \n%s" % stack_trace
         if self.options.redirect_logs:
             print(info)
-        elif self.options.xunit_file:
+            return
+
+        if self.options.xunit_file:
             self.stack_trace = stack_trace
-        else:
-            with open(self.logfile, 'a') as f:
-                f.write(info)
+
+        with open(self.logfile, 'a') as f:
+            f.write(info)
 
     def set_result(self, result, message="", error=""):
         self.debug("Setting result: %s (message: %s, error: %s)" % (result,
@@ -638,12 +641,8 @@ class GstValidateListener(socketserver.BaseRequestHandler):
 class GstValidateTest(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
+    fault_sig_regex = re.compile("<Caught SIGNAL: .*>")
 
     def __init__(self, application_name, classname,
                  options, reporter, duration=0,
@@ -908,11 +907,16 @@ class GstValidateTest(Test):
         msg = ""
         result = Result.PASSED
         if self.result == Result.TIMEOUT:
-            if expected_timeout:
-                not_found_expected_failures.remove(expected_timeout)
-                result, msg = self.check_expected_timeout(expected_timeout)
-            else:
-                return
+            with open(self.logfile) as f:
+                signal_fault_info = self.fault_sig_regex.findall(f.read())
+                if signal_fault_info:
+                    result = Result.FAILED
+                    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:
             result = Result.FAILED
             msg = "Application segfaulted "
index 9aa08aa..ffb6814 100644 (file)
@@ -33,6 +33,7 @@
 #include <gst/validate/media-descriptor-writer.h>
 #include <gst/validate/media-descriptor-parser.h>
 #include <gst/validate/media-descriptor.h>
+#include <gst/validate/gst-validate-utils.h>
 #include <gst/pbutils/encoding-profile.h>
 #include <locale.h>             /* for LC_ALL */
 
@@ -102,6 +103,8 @@ main (int argc, gchar ** argv)
   }
   g_option_context_free (ctx);
 
+  gst_validate_spin_on_fault_signals ();
+
   runner = gst_validate_runner_new ();
 
   if (expected_file) {
index 1d2d08e..2ff5f81 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <gst/gst.h>
 #include <gst/video/video.h>
+#include <gst/validate/gst-validate-utils.h>
 #include <gst/validate/validate.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);
 #endif
 
+  gst_validate_spin_on_fault_signals ();
+
   monitor =
       gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline), runner,
       NULL);
index b409ed3..e7399e2 100644 (file)
@@ -457,6 +457,8 @@ main (int argc, gchar ** argv)
       g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
 #endif
 
+  gst_validate_spin_on_fault_signals ();
+
   if (_is_playbin_pipeline (argc - 1, argv + 1)) {
     _register_playbin_actions ();
   }