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