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
sigfpe(int sig,siginfo_t * si,void * v)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
main(int argc,char * argv[])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