1 /* $OpenBSD: except.c,v 1.12 2010/05/08 19:16:33 naddy Exp $ */ 2 3 #include <sys/types.h> 4 #include <unistd.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <signal.h> 9 #include <assert.h> 10 #include <ieeefp.h> 11 #include <float.h> 12 #include <err.h> 13 14 volatile sig_atomic_t signal_status; 15 16 volatile const double one = 1.0; 17 volatile const double zero = 0.0; 18 volatile const double huge = DBL_MAX; 19 volatile const double tiny = DBL_MIN; 20 21 void 22 sigfpe(int sig, siginfo_t *si, void *v) 23 { 24 char buf[132]; 25 26 if (si) { 27 snprintf(buf, sizeof(buf), "sigfpe: addr=%p, code=%d\n", 28 si->si_addr, si->si_code); 29 write(1, buf, strlen(buf)); 30 } 31 _exit(signal_status); 32 } 33 34 35 int 36 main(int argc, char *argv[]) 37 { 38 struct sigaction sa; 39 volatile double x; 40 41 if (argc != 2) { 42 fprintf(stderr, "usage: %s condition\n", argv[0]); 43 exit(1); 44 } 45 46 /* 47 * check to make sure that all exceptions are masked and 48 * that the accumulated exception status is clear. 49 */ 50 assert(fpgetmask() == 0); 51 assert(fpgetsticky() == 0); 52 53 memset(&sa, 0, sizeof(sa)); 54 sa.sa_sigaction = sigfpe; 55 sa.sa_flags = SA_SIGINFO; 56 sigaction(SIGFPE, &sa, NULL); 57 signal_status = 1; 58 59 if (strcmp(argv[1], "fltdiv") == 0) { 60 /* trip divide by zero */ 61 x = one / zero; 62 assert(fpgetsticky() & FP_X_DZ); 63 fpsetsticky(0); 64 65 /* and now unmask to get a signal */ 66 signal_status = 0; 67 fpsetmask(FP_X_DZ); 68 x = one / zero; 69 } else if (strcmp(argv[1], "fltinv") == 0) { 70 /* trip invalid operation */ 71 x = zero / zero; 72 assert(fpgetsticky() & FP_X_INV); 73 fpsetsticky(0); 74 75 /* and now unmask to get a signal */ 76 signal_status = 0; 77 fpsetmask(FP_X_INV); 78 x = zero / zero; 79 } else if (strcmp(argv[1], "fltovf") == 0) { 80 /* trip overflow */ 81 x = huge * huge; 82 assert(fpgetsticky() & FP_X_OFL); 83 fpsetsticky(0); 84 85 /* and now unmask to get a signal */ 86 signal_status = 0; 87 fpsetmask(FP_X_OFL); 88 x = huge * huge; 89 } else if (strcmp(argv[1], "fltund") == 0) { 90 /* trip underflow */ 91 x = tiny * tiny; 92 assert(fpgetsticky() & FP_X_UFL); 93 fpsetsticky(0); 94 95 /* and now unmask to get a signal */ 96 signal_status = 0; 97 fpsetmask(FP_X_UFL); 98 x = tiny * tiny; 99 } else { 100 errx(1, "unrecognized condition %s", argv[1]); 101 } 102 103 /* 104 * attempt to trigger the exception on machines where 105 * floating-point exceptions are deferred. 106 */ 107 x = one * one; 108 109 errx(1, "signal wasn't caught"); 110 } 111