diff options
-rwxr-xr-x | configure | 19 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | src/H5config.h.in | 9 | ||||
-rw-r--r-- | src/H5detect.c | 259 |
4 files changed, 222 insertions, 70 deletions
@@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Id: configure.in 18634 2010-04-27 18:25:31Z koziol . +# From configure.in Id: configure.in 18648 2010-04-27 21:35:53Z songyulu . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for HDF5 1.9.68. # @@ -24825,7 +24825,7 @@ _ACEOF fi done -for ac_func in gethostname getpwuid getrusage longjmp lstat +for ac_func in gethostname getpwuid getrusage lstat do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -24838,7 +24838,20 @@ _ACEOF fi done -for ac_func in rand_r random setsysinfo siglongjmp signal +for ac_func in rand_r random setsysinfo +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in signal longjmp setjmp siglongjmp sigsetjmp sigprocmask do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.in b/configure.in index 218dfcd..0720e07 100644 --- a/configure.in +++ b/configure.in @@ -1978,8 +1978,9 @@ dnl ---------------------------------------------------------------------- dnl Check for functions. dnl AC_CHECK_FUNCS(alarm BSDgettimeofday fork frexpf frexpl) -AC_CHECK_FUNCS(gethostname getpwuid getrusage longjmp lstat) -AC_CHECK_FUNCS(rand_r random setsysinfo siglongjmp signal) +AC_CHECK_FUNCS(gethostname getpwuid getrusage lstat) +AC_CHECK_FUNCS(rand_r random setsysinfo) +AC_CHECK_FUNCS(signal longjmp setjmp siglongjmp sigsetjmp sigprocmask) AC_CHECK_FUNCS(snprintf srandom strdup symlink system) AC_CHECK_FUNCS(tmpfile vasprintf waitpid) diff --git a/src/H5config.h.in b/src/H5config.h.in index ef072de..8210f38 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -253,6 +253,9 @@ /* Define to 1 if you have the `rand_r' function. */ #undef HAVE_RAND_R +/* Define to 1 if you have the `setjmp' function. */ +#undef HAVE_SETJMP + /* Define to 1 if you have the <setjmp.h> header file. */ #undef HAVE_SETJMP_H @@ -265,6 +268,12 @@ /* Define to 1 if you have the `signal' function. */ #undef HAVE_SIGNAL +/* Define to 1 if you have the `sigprocmask' function. */ +#undef HAVE_SIGPROCMASK + +/* Define to 1 if you have the `sigsetjmp' function. */ +#undef HAVE_SIGSETJMP + /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF diff --git a/src/H5detect.c b/src/H5detect.c index ac1185f..1cfce96 100644 --- a/src/H5detect.c +++ b/src/H5detect.c @@ -59,6 +59,32 @@ static const char *FileHeader = "\n\ #include "H5Rpublic.h" #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 + * do. If sigsetjmp/siglongjmp are not supported, need to use sigprocmask to + * unblock the signal before doing longjmp. + */ +/* Define H5SETJMP/H5LONGJMP depending on if sigsetjmp/siglongjmp are */ +/* supported. */ +#if defined(H5_HAVE_SIGSETJMP) && defined(H5_HAVE_SIGLONGJMP) +/* Always save blocked signals to be restore by siglongjmp. */ +#define H5JMP_BUF sigjmp_buf +#define H5SETJMP(buf) sigsetjmp(buf, 1) +#define H5LONGJMP(buf, val) siglongjmp(buf, val) +#define H5HAVE_SIGJMP # sigsetjmp/siglongjmp are supported. +#elif defined(H5_HAVE_LONGJMP) +#define H5JMP_BUF jmp_buf +#define H5SETJMP(buf) setjmp(buf) +#define H5LONGJMP(buf, val) longjmp(buf, val) +#endif + +/* ALIGNMENT and signal-handling status codes */ +#define STA_NoALIGNMENT 0x0001 /* No ALIGNMENT Test */ +#define STA_NoHandlerVerify 0x0002 /* No signal handler Tests */ + + /* * This structure holds information about a type that * was detected. @@ -109,7 +135,16 @@ static void detect_C99_integers32(void); static void detect_C99_integers64(void); static void detect_alignments(void); static size_t align_g[] = {1, 2, 4, 8, 16}; -static jmp_buf jbuf_g; +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 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)); +#endif +#ifdef H5JMP_BUF +static H5JMP_BUF jbuf_g; +#endif /*------------------------------------------------------------------------- @@ -350,20 +385,20 @@ precision (detected_t *d) COMP_ALIGN = (size_t)((char*)(&(s.x)) - (char*)(&s)); \ } -#if defined(H5_HAVE_LONGJMP) && defined(H5_HAVE_SIGNAL) +#if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL) #define ALIGNMENT(TYPE,INFO) { \ char *volatile _buf = NULL; \ volatile TYPE _val = 1; \ volatile TYPE _val2; \ volatile size_t _ano = 0; \ - void (*_handler)(int) = signal(SIGBUS, sigbus_handler); \ - void (*_handler2)(int) = signal(SIGSEGV, sigsegv_handler); \ + void (*_handler)(int) = HDsignal(SIGBUS, sigbus_handler); \ + void (*_handler2)(int) = HDsignal(SIGSEGV, sigsegv_handler);\ \ _buf = (char*)malloc(sizeof(TYPE) + align_g[NELMTS(align_g) - 1]); \ - if(setjmp(jbuf_g)) _ano++; \ + if(H5SETJMP(jbuf_g)) _ano++; \ if(_ano < NELMTS(align_g)) { \ - *((TYPE*)(_buf+align_g[_ano])) = _val; /*possible SIGBUS or SEGSEGV*/ \ - _val2 = *((TYPE*)(_buf+align_g[_ano])); /*possible SIGBUS or SEGSEGV*/ \ + *((TYPE*)(_buf+align_g[_ano])) = _val; /*possible SIGBUS or SEGSEGV*/ \ + _val2 = *((TYPE*)(_buf+align_g[_ano])); /*possible SIGBUS or SEGSEGV*/\ /* Cray Check: This section helps detect alignment on Cray's */ \ /* vector machines (like the SV1) which mask off */ \ /* pointer values when pointing to non-word aligned */ \ @@ -377,7 +412,7 @@ precision (detected_t *d) memcpy(_buf+align_g[_ano]+(INFO.offset/8),((char *)&_val)+(INFO.offset/8),(size_t)(INFO.precision/8)); \ _val2 = *((TYPE*)(_buf+align_g[_ano])); \ if(_val!=_val2) \ - longjmp(jbuf_g, 1); \ + H5LONGJMP(jbuf_g, 1); \ /* End Cray Check */ \ (INFO.align)=align_g[_ano]; \ } else { \ @@ -385,61 +420,18 @@ precision (detected_t *d) fprintf(stderr, "unable to calculate alignment for %s\n", #TYPE); \ } \ free(_buf); \ - signal(SIGBUS, _handler); /*restore original handler*/ \ - signal(SIGSEGV, _handler2); /*restore original handler*/ \ + HDsignal(SIGBUS, _handler); /*restore original handler*/ \ + HDsignal(SIGSEGV, _handler2); /*restore original handler*/ \ } #else -#define ALIGNMENT(TYPE,INFO) (INFO.align)=0 -#endif - -#if 0 -#if defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID) #define ALIGNMENT(TYPE,INFO) { \ - char *_buf; \ - TYPE _val=0; \ - size_t _ano; \ - pid_t _child; \ - int _status; \ - \ - srand((unsigned int)_val); /*suppress "set but unused" warning*/ \ - for (_ano=0; _ano<NELMTS(align_g); _ano++) { \ - fflush(stdout); \ - fflush(stderr); \ - if (0==(_child=fork())) { \ - _buf = malloc(sizeof(TYPE)+align_g[NELMTS(align_g)-1]); \ - *((TYPE*)(_buf+align_g[_ano])) = _val; \ - _val = *((TYPE*)(_buf+align_g[_ano])); \ - free(_buf); \ - exit(0); \ - } else if (_child<0) { \ - perror("fork"); \ - exit(1); \ - } \ - if (waitpid(_child, &_status, 0)<0) { \ - perror("waitpid"); \ - exit(1); \ - } \ - if (WIFEXITED(_status) && 0==WEXITSTATUS(_status)) { \ - INFO.align=align_g[_ano]; \ - break; \ - } \ - if (WIFSIGNALED(_status) && SIGBUS==WTERMSIG(_status)) { \ - continue; \ - } \ - _ano=NELMTS(align_g); \ - break; \ - } \ - if (_ano>=NELMTS(align_g)) { \ - INFO.align=0; \ - fprintf(stderr, "unable to calculate alignment for %s\n", #TYPE); \ - } \ + align_status_g |= STA_NoALIGNMENT; \ + (INFO.align)=0; \ } -#else -#define ALIGNMENT(TYPE,INFO) (INFO.align)=0 -#endif #endif +#if defined(H5LONGJMP) && defined(H5_HAVE_SIGNAL) /*------------------------------------------------------------------------- * Function: sigsegv_handler * @@ -448,7 +440,7 @@ precision (detected_t *d) * it's not nearly as nice to work with, it does the job for * this simple stuff. * - * Return: Returns via longjmp to jbuf_g. + * Return: Returns via H5LONGJMP to jbuf_g. * * Programmer: Robb Matzke * Thursday, March 18, 1999 @@ -460,11 +452,24 @@ precision (detected_t *d) static void sigsegv_handler(int UNUSED signo) { - signal(SIGSEGV, sigsegv_handler); - longjmp(jbuf_g, 1); +#if !defined(H5HAVE_SIGJMP) && defined(H5_HAVE_SIGPROCMASK) + /* Use sigprocmask to unblock the signal if sigsetjmp/siglongjmp are not */ + /* supported. */ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGSEGV); + sigprocmask(SIG_UNBLOCK, &set, NULL); +#endif + + sigsegv_handler_called_g++; + HDsignal(SIGSEGV, sigsegv_handler); + H5LONGJMP(jbuf_g, SIGSEGV); } +#endif +#if defined(H5LONGJMP) && defined(H5_HAVE_SIGNAL) /*------------------------------------------------------------------------- * Function: sigbus_handler * @@ -473,7 +478,7 @@ sigsegv_handler(int UNUSED signo) * it's not nearly as nice to work with, it does the job for * this simple stuff. * - * Return: Returns via longjmp to jbuf_g. + * Return: Returns via H5LONGJMP to jbuf_g. * * Programmer: Robb Matzke * Thursday, March 18, 1999 @@ -485,12 +490,21 @@ sigsegv_handler(int UNUSED signo) static void sigbus_handler(int UNUSED signo) { - signal(SIGBUS, sigbus_handler); - longjmp(jbuf_g, 1); -#ifdef H5_HAVE_SIGLONGJMP - siglongjmp(jbuf_g, 1); -#endif /* H5_HAVE_SIGLONGJMP */ +#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, SIGBUS); + HDsigprocmask(SIG_UNBLOCK, &set, NULL); +#endif + + sigbus_handler_called_g++; + HDsignal(SIGBUS, sigbus_handler); + H5LONGJMP(jbuf_g, SIGBUS); } +#endif /*------------------------------------------------------------------------- @@ -574,6 +588,7 @@ print_results(int nd, detected_t *d, int na, malign_t *misc_align) /*******************/\n\ \n"); + /* The interface initialization function */ printf("\n\ \n\ @@ -721,6 +736,57 @@ done:\n\ } /* end if */\n\ \n\ FUNC_LEAVE_NOAPI(ret_value);\n} /* end H5TN_init_interface() */\n"); + + /* Print the ALIGNMENT and signal-handling status as comments */ + printf("\n" + "/****************************************/\n" + "/* ALIGNMENT and signal-handling status */\n" + "/****************************************/\n"); + if (align_status_g & STA_NoALIGNMENT) + printf("/* ALIGNAMENT test is not available */\n"); + if (align_status_g & STA_NoHandlerVerify) + printf("/* Signal handlers verify test is not available */\n"); + /* The following is available in H5pubconf.h. Printing them here for */ + /* convenience. */ +#ifdef H5_HAVE_SIGNAL + printf("/* Signal() support: yes */\n"); +#else + printf("/* Signal() support: no */\n"); +#endif +#ifdef H5_HAVE_SETJMP + printf("/* setjmp() support: yes */\n"); +#else + printf("/* setjmp() support: no */\n"); +#endif +#ifdef H5_HAVE_LONGJMP + printf("/* longjmp() support: yes */\n"); +#else + printf("/* longjmp() support: no */\n"); +#endif +#ifdef H5_HAVE_SIGSETJMP + printf("/* sigsetjmp() support: yes */\n"); +#else + printf("/* sigsetjmp() support: no */\n"); +#endif +#ifdef H5_HAVE_SIGLONGJMP + printf("/* siglongjmp() support: yes */\n"); +#else + printf("/* siglongjmp() support: no */\n"); +#endif +#ifdef H5_HAVE_SIGPROCMASK + printf("/* sigprocmask() support: yes */\n"); +#else + printf("/* sigprocmask() support: no */\n"); +#endif + + /* Print the statics of signal handlers called for debugging */ + printf("\n" + "/******************************/\n" + "/* signal handlers statistics */\n" + "/******************************/\n"); + printf("/* signal_handlers tested: %d times */\n", signal_handler_tested_g); + printf("/* sigbus_handler called: %d times */\n", sigbus_handler_called_g); + printf("/* sigsegv_handler called: %d times */\n", sigsegv_handler_called_g); } /* end print_results() */ @@ -1485,6 +1551,55 @@ detect_alignments(void) } +#if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL) +/* Verify the signal handler for signal signum works correctly multiple times. + * One possible cause of failure is that the signal handling is blocked or + * changed to SIG_DFL after H5LONGJMP. + * Return 0 for success, -1 for failure. + */ +static int verify_signal_handlers(int signum, void (*handler)(int)) +{ + void (*save_handler)(int) = HDsignal(signum, handler); + int i, val; + int ntries=5; + volatile int nfailures=0; + volatile int nsuccesses=0; + + for (i=0;i<ntries; i++){ + val=H5SETJMP(jbuf_g); + if (val==0) + { + /* send self the signal to trigger the handler */ + signal_handler_tested_g++; + HDraise(signum); + /* Should not reach here. Record error. */ + nfailures++; + }else{ + if (val==signum){ + /* return from signum handler. Record a sucess. */ + nsuccesses++; + }else{ + fprintf(stderr, "Unknown return value (%d) from H5SETJMP", + val); + nfailures++; + } + } + } + /* restore save handler, check results and report failures */ + HDsignal(signum, save_handler); + if (nfailures>0 || nsuccesses != ntries){ + fprintf(stderr, "verify_signal_handlers for signal %d did %d tries. " + "Found %d failures and %d successes\n", + signum, ntries, nfailures, nsuccesses); + return(-1); + }else{ + /* all succeeded */ + return(0); + } +} +#endif + + /*------------------------------------------------------------------------- * Function: main * @@ -1527,6 +1642,20 @@ main(void) #endif #endif +#if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL) + /* verify the SIGBUS and SIGSEGV handlers work properly */ + if (verify_signal_handlers (SIGBUS, sigbus_handler) != 0){ + fprintf(stderr, "Signal handler %s for signal %d failed\n", + "sigbus_handler", SIGBUS); + } + if (verify_signal_handlers (SIGSEGV, sigsegv_handler) != 0){ + fprintf(stderr, "Signal handler %s for signal %d failed\n", + "sigsegv_handler", SIGSEGV); + } +#else + align_status_g |= STA_NoHandlerVerify; +#endif + print_header(); /* C89 integer types */ |