[Piglit] [PATCH 03/13] util: Implement signal handler support.
Kenney Phillis
kphillisjr at gmail.com
Thu Oct 31 15:47:59 CET 2013
* Non-Posix compliant platforms - Only a stub for a signal handler exists.
* Posix platforms - Add support for simple backtrace support when a crash is
detected. This support does not interfere with valgrind and gdb testing.
When running a program in the debugger ( for example, GDB ), the singal handler
is only handled after you resume the program using the the signal handler.
---
CMakeLists.txt | 9 +
tests/util/CMakeLists.txt | 9 +
tests/util/config.h.in | 5 +
.../piglit-sighandler/piglit-sighandler-none.c | 37 ++++
.../piglit-sighandler/piglit-sighandler-posix.c | 209 ++++++++++++++++++++
tests/util/piglit-util.h | 12 ++
6 files changed, 281 insertions(+)
create mode 100644 tests/util/piglit-sighandler/piglit-sighandler-none.c
create mode 100644 tests/util/piglit-sighandler/piglit-sighandler-posix.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 21eebc5..03e1490 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -314,12 +314,21 @@ check_function_exists(strndup HAVE_STRNDUP)
check_function_exists(fopen_s HAVE_FOPEN_S)
check_function_exists(setrlimit HAVE_SETRLIMIT)
+check_include_file(execinfo.h HAVE_EXECINFO_H)
+check_include_file(signal.h HAVE_SIGNAL_H)
+check_include_file(syscall.h HAVE_SYSCALL_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H)
+check_include_file(sys/siginfo.h HAVE_SYS_SIGINFO_H)
check_include_file(sys/stat.h HAVE_SYS_STAT_H)
+check_include_file(sys/syscall.h HAVE_SYS_SYSCALL_H)
check_include_file(unistd.h HAVE_UNISTD_H)
+#TODO: Implement proper libunwind support.
+#check_include_file(unwind.h HAVE_UNWIND_H)
+#check_include_file(libunwind.h HAVE_LIBUNWIND_H)
check_include_file(fcntl.h HAVE_FCNTL_H)
+check_include_file(wait.h HAVE_WAIT_H)
configure_file(
"${piglit_SOURCE_DIR}/tests/util/config.h.in"
diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt
index dcc5634..5c184ea 100644
--- a/tests/util/CMakeLists.txt
+++ b/tests/util/CMakeLists.txt
@@ -9,6 +9,15 @@ set(UTIL_SOURCES
piglit-util.c
)
+
+# Auto-detect Correct Signal Handler.
+if(UNIX)
+ list(APPEND UTIL_SOURCES piglit-sighandler/piglit-sighandler-posix.c)
+else()
+ # No Signal Handler found.
+ list(APPEND UTIL_SOURCES piglit-sighandler/piglit-sighandler-none.c)
+endif()
+
set(UTIL_GL_INCLUDES
${UTIL_INCLUDES}
${GLEXT_INCLUDE_DIR}
diff --git a/tests/util/config.h.in b/tests/util/config.h.in
index 2e8262a..b75e1f7 100644
--- a/tests/util/config.h.in
+++ b/tests/util/config.h.in
@@ -3,9 +3,14 @@
#cmakedefine HAVE_SETRLIMIT
#cmakedefine HAVE_STRNDUP
+#cmakedefine HAVE_EXECINFO_H
#cmakedefine HAVE_FCNTL_H
+#cmakedefine HAVE_LIBUNWIND_H
+#cmakedefine HAVE_SIGNAL_H
#cmakedefine HAVE_SYS_STAT_H
#cmakedefine HAVE_SYS_TYPES_H
#cmakedefine HAVE_SYS_TIME_H
#cmakedefine HAVE_SYS_RESOURCE_H
+#cmakedefine HAVE_SYS_SIGINFO_H
#cmakedefine HAVE_UNISTD_H
+#cmakedefine HAVE_UNWIND_H
diff --git a/tests/util/piglit-sighandler/piglit-sighandler-none.c b/tests/util/piglit-sighandler/piglit-sighandler-none.c
new file mode 100644
index 0000000..9b98976
--- /dev/null
+++ b/tests/util/piglit-sighandler/piglit-sighandler-none.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2013 Kenney Phillis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "piglit-util.h"
+
+/** @file piglit-sighandler-none.c
+ *
+ * A stub to fill in the piglit_register_signal_handler function.
+ *
+ */
+
+#warning "Piglit Segmentation Handler Not Implemented for Your Platform."
+bool piglit_register_signal_handler()
+{
+ /* Nothing to Do */
+ return false;
+}
diff --git a/tests/util/piglit-sighandler/piglit-sighandler-posix.c b/tests/util/piglit-sighandler/piglit-sighandler-posix.c
new file mode 100644
index 0000000..63b31c9
--- /dev/null
+++ b/tests/util/piglit-sighandler/piglit-sighandler-posix.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright © 2013 Kenney Phillis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file piglit-sighandler-posix.c
+ *
+ * Implements posix compatible signal handler.
+ *
+ */
+#include "config.h"
+#include "piglit-util.h"
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#if defined(HAVE_SYS_TYPES_H)
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAVE_SYS_SIGINFO_H
+#include <sys/siginfo.h>
+#endif
+
+#ifdef HAVE_SYSCALL_H
+#include <syscall.h>
+#elif defined( HAVE_SYS_SYSCALL_H )
+#include <sys/syscall.h>
+#endif
+
+// for Backtrace Support
+#if defined(HAVE_LIBUNWIND_H)
+#include <libunwind.h>
+#elif defined(HAVE_EXECINFO_H)
+#include <execinfo.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#elif defined( HAVE_WAIT_H)
+#include <wait.h>
+#endif
+
+void piglit_sighandler(int sig, siginfo_t *info, void *secret);
+bool piglit_sighandler_gdb_report( char*name_buf, char* pid_buf);
+void piglit_sighandler_backtrace(int sig, siginfo_t *info, void *secret);
+
+bool piglit_register_signal_handler()
+{
+ /* Register the Piglit signal action handler. */
+ struct sigaction sa;
+ sigset_t block_mask;
+ sigemptyset (&block_mask);
+ /**
+ * Most signals are already set to need a block. However, this is the
+ * only signal that you absolutely haft to block to be able to capture
+ * output
+ */
+ sigaddset (&block_mask, SIGABRT);
+ sigaddset (&block_mask, SIGINT);
+ sigaddset (&block_mask, SIGQUIT);
+ sa.sa_handler = (void *)piglit_sighandler;
+ sa.sa_mask = block_mask;
+ sa.sa_flags = 0;
+#ifdef SA_SIGINFO
+ sa.sa_flags |= SA_SIGINFO;
+ sa.sa_sigaction = (void *)piglit_sighandler;
+#endif
+#ifdef SA_RESTART
+ sa.sa_flags |= SA_RESTART;
+#endif
+ /* Actually Register the Signal Actions */
+ sigaction( SIGTRAP, &sa, NULL); /* 5 - Trace trap (POSIX) */
+ sigaction( SIGABRT, &sa, NULL); /* 6 - Abort ( ANSI )*/
+ sigaction( SIGFPE, &sa, NULL); /* 8 - FPE ( Floating Point Exception) */
+ sigaction( SIGUSR1, &sa, NULL); /* 10 - User Defined Signal*/
+ sigaction( SIGSEGV, &sa, NULL); /* 11 - Segmentation Fault */
+
+ return true;
+}
+
+
+
+void piglit_sighandler(int sig, siginfo_t *info, void *secret) {
+ char proc_pid_buf[30];
+ char proc_name_buf[512];
+ // Get executable name.
+ proc_name_buf[readlink("/proc/self/exe", proc_name_buf, 511)]='\0';
+ sprintf(proc_pid_buf, "%d", getpid());
+ fprintf(stdout,"\nPiglit: Crash Detected on %s ( PID: %s ).\n"
+ "\tGenerating Debug information\n", proc_name_buf, proc_pid_buf);
+ fprintf(stdout,"info.si_signo = %d\n", sig);
+ fprintf(stdout,"info.si_code = %d\n", info->si_code);
+ fprintf(stdout,"info.si_addr = %p\n", info->si_addr);
+ fprintf(stdout,"info.si_errno = %d\n", info->si_errno);
+ piglit_sighandler_backtrace(sig, info, secret);
+
+ fprintf(stdout,"PIGLIT: {'result': 'crash' }\n");
+ fflush(stdout);
+
+ /* Maintain the Signal, and use that as the return code. */
+ exit(sig);
+}
+
+void piglit_sighandler_backtrace(int sig, siginfo_t *info, void *secret)
+{
+#if defined( HAVE_UNWIND_H)
+ /* Unwind Capable */
+ unw_context_t uc;
+ unw_cursor_t cursor;
+ unw_word_t ip, sp, offp;
+ char functionName[256];
+ int res;
+ /* Initialize the Context */
+ unw_getcontext(&uc);
+ unw_init_local(&cursor, &uc);
+ while (unw_step(&cursor) !=0)
+ {
+
+ functionName[0] = '\0';
+ res = unw_get_proc_name(&cursor, functionName, 256, &offp);
+ if(res == UNW_EUNSPEC) {
+ printf ("ERROR: unwind: Unspecified Error.");
+ continue;
+ }
+ if(res == UNW_ENOINFO){
+ printf ("ERROR: unwind: Unspecified to determine Name of Procedure.\n");
+ continue;
+ }
+ unw_get_reg(&cursor, UNW_REG_IP, &ip); /* Instruction Pointer*/
+ unw_get_reg(&cursor, UNW_REG_SP, &sp); /* Stack Pointer*/
+#ifdef UNW_ENOMME
+ if(res== UNW_ENOMME) {
+ printf ("Warning: unwind: Procedure Name to Long... Name is Truncated.\n");
+ }
+#endif
+#if __WORDSIZE == 64
+ /* Print Stack Pointer and Instruction Pointer */
+ printf ("SP=0x%016lx IP=0x%016lx" ,sp, ip);
+ /* Print Symbol name and Instruction Offset */
+ printf (": (%s+0x%016lx) [%016lx]\n", functionName, offp, ip);
+#elif __WORDSIZE == 32
+ /* Print Stack Pointer and Instruction Pointer */
+ printf ("SP=0x%08x IP=0x%08x" ,sp, ip);
+ /* Print Symbol name and Instruction Offset */
+ printf (": (%s+0x%08x) [%08x]\n", functionName, offp, ip);
+#else
+ /* Print Stack Pointer and Instruction Pointer */
+ printf ("SP=0x%04x IP=0x%04x" ,sp, ip);
+ /* Print Symbol name and Instruction Offset */
+ printf (": (%s+0x%04x) [%04x]\n", functionName, offp, ip);
+#endif
+ }
+#elif defined(HAVE_EXECINFO_H)
+ void *trace[16];
+ char **messages = (char **)NULL;
+ int i, trace_size = 0;
+ trace_size = backtrace(trace, 16);
+ /* overwrite sigaction with caller's address */
+ //trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
+
+ messages = backtrace_symbols(trace, trace_size);
+ /* skip first stack frame (points here) */
+ printf("[backtrace] Execution path\n");
+ for (i=0; i<trace_size; ++i) {
+ fprintf(stderr,"%d - %s\n",i, messages[i]);
+ }
+#else
+ fprintf(stdout,"Piglit: Warning, Unable to generate Backtraces.\n");
+#endif
+}
diff --git a/tests/util/piglit-util.h b/tests/util/piglit-util.h
index f9f70f3..088ef9a 100644
--- a/tests/util/piglit-util.h
+++ b/tests/util/piglit-util.h
@@ -111,6 +111,18 @@ enum piglit_result {
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
/**
+ * Register platform specific signal handler.
+
+ * This Signal handler is used to automatically generate call stacks
+ * when a test crashes.
+ *
+ * \precondition \c Some call stacks will not completely register.
+ * For example, SIGABRT on linux is already after test terminates.
+ *
+ */
+bool piglit_register_signal_handler();
+
+/**
* Determine if an extension is listed in an extension string
*
* \param haystack List of all extensions to be searched
--
1.7.9.5
More information about the Piglit
mailing list