summaryrefslogtreecommitdiffstats
path: root/src/H5detect.c
diff options
context:
space:
mode:
authorRaymond Lu <songyulu@hdfgroup.org>2013-10-28 21:25:46 (GMT)
committerRaymond Lu <songyulu@hdfgroup.org>2013-10-28 21:25:46 (GMT)
commit2eb24b16dac78b3e27769c20502299475fb8dde6 (patch)
tree98d1ebfe8439fa9d557a00cc3602f74d3f8e8981 /src/H5detect.c
parent56803a19704bf20f83267bdbf3ab32bf9ed1e375 (diff)
downloadhdf5-2eb24b16dac78b3e27769c20502299475fb8dde6.zip
hdf5-2eb24b16dac78b3e27769c20502299475fb8dde6.tar.gz
hdf5-2eb24b16dac78b3e27769c20502299475fb8dde6.tar.bz2
[svn-r24368] Issue 8147 - clang's -fcatch-undefined-behavior exposed undefined behavior in the alignment detection algorithm for integers in H5detect.c. Quincey decided to solve it in two steps. First, catch illegal instruction signal in the original algorithm. Second, use POSIX __alignof function to detect alignment if it's available. This checkin is the first step.
Tested on wren, jam, ostrich, platypas, and koala.
Diffstat (limited to 'src/H5detect.c')
-rw-r--r--src/H5detect.c47
1 files changed, 43 insertions, 4 deletions
diff --git a/src/H5detect.c b/src/H5detect.c
index 3554d50..0f8d051 100644
--- a/src/H5detect.c
+++ b/src/H5detect.c
@@ -60,9 +60,9 @@ static const char *FileHeader = "\n\
#define MAXDETECT 64
-/* The ALIGNMENT test code may generate the SIGBUS or SIGSEGV signals. We use
- * setjmp/longjmp in the signal handlers for recovery. But setjmp/longjmp do
- * not necessary restore the signal blocking status while sigsetjmp/siglongjmp
+/* The ALIGNMENT test code may generate the SIGBUS, SIGSEGV, or SIGILL signals.
+ * We use setjmp/longjmp in the signal handlers for recovery. But setjmp/longjmp
+ * do not necessary restore the signal blocking status while sigsetjmp/siglongjmp
* do. If sigsetjmp/siglongjmp are not supported, need to use sigprocmask to
* unblock the signal before doing longjmp.
*/
@@ -139,7 +139,8 @@ static void detect_alignments(void);
static size_t align_g[] = {1, 2, 4, 8, 16};
static int align_status_g = 0; /* ALIGNMENT Signal Status */
static int sigbus_handler_called_g = 0; /* how many times called */
-static int sigsegv_handler_called_g = 0; /* how many times called */
+static int sigsegv_handler_called_g = 0;/* how many times called */
+static int sigill_handler_called_g = 0; /* how many times called */
static int signal_handler_tested_g = 0; /* how many times tested */
#if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL)
static int verify_signal_handlers(int signum, void (*handler)(int));
@@ -425,6 +426,7 @@ precision (detected_t *d)
volatile size_t _ano = 0; \
void (*_handler)(int) = HDsignal(SIGBUS, sigbus_handler); \
void (*_handler2)(int) = HDsignal(SIGSEGV, sigsegv_handler);\
+ void (*_handler3)(int) = HDsignal(SIGILL, sigill_handler); \
\
_buf = (char*)HDmalloc(sizeof(TYPE) + align_g[NELMTS(align_g) - 1]); \
if(H5SETJMP(jbuf_g)) _ano++; \
@@ -454,6 +456,7 @@ precision (detected_t *d)
HDfree(_buf); \
HDsignal(SIGBUS, _handler); /*restore original handler*/ \
HDsignal(SIGSEGV, _handler2); /*restore original handler*/ \
+ HDsignal(SIGILL, _handler3); /*restore original handler*/ \
}
#else
#define ALIGNMENT(TYPE,INFO) { \
@@ -539,6 +542,42 @@ sigbus_handler(int UNUSED signo)
#endif
+#if defined(H5LONGJMP) && defined(H5_HAVE_SIGNAL)
+/*-------------------------------------------------------------------------
+ * Function: sigill_handler
+ *
+ * Purpose: Handler for SIGILL. We use signal() instead of sigaction()
+ * because it's more portable to non-Posix systems. Although
+ * it's not nearly as nice to work with, it does the job for
+ * this simple stuff.
+ *
+ * Return: Returns via H5LONGJMP to jbuf_g.
+ *
+ * Programmer: Raymond Lu
+ * 28 October 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+sigill_handler(int UNUSED signo)
+{
+#if !defined(H5HAVE_SIGJMP) && defined(H5_HAVE_SIGPROCMASK)
+ /* Use sigprocmask to unblock the signal if sigsetjmp/siglongjmp are not */
+ /* supported. */
+ sigset_t set;
+
+ HDsigemptyset(&set);
+ HDsigaddset(&set, SIGILL);
+ HDsigprocmask(SIG_UNBLOCK, &set, NULL);
+#endif
+
+ sigill_handler_called_g++;
+ HDsignal(SIGILL, sigill_handler);
+ H5LONGJMP(jbuf_g, SIGILL);
+}
+#endif
+
+
/*-------------------------------------------------------------------------
* Function: print_results
*