Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7d4266e

Browse files
committed
Changes for Lee Busby's SIGFPE patch set.
New file pyfpe.h, new exception FloatingPointError.
1 parent 1ca407f commit 7d4266e

4 files changed

Lines changed: 168 additions & 0 deletions

File tree

Include/allobjects.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,6 @@ PERFORMANCE OF THIS SOFTWARE.
113113
#include "rename2.h"
114114
#endif
115115

116+
#include "pyfpe.h"
117+
116118
#endif /* !Py_ALLOBJECTS_H */

Include/pyerrors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ extern DL_IMPORT(PyObject *) PyExc_AccessError;
5151
extern DL_IMPORT(PyObject *) PyExc_AttributeError;
5252
extern DL_IMPORT(PyObject *) PyExc_ConflictError;
5353
extern DL_IMPORT(PyObject *) PyExc_EOFError;
54+
extern DL_IMPORT(PyObject *) PyExc_FloatingPointError;
5455
extern DL_IMPORT(PyObject *) PyExc_IOError;
5556
extern DL_IMPORT(PyObject *) PyExc_ImportError;
5657
extern DL_IMPORT(PyObject *) PyExc_IndexError;

Include/pyfpe.h

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#ifndef Py_PYFPE_H
2+
#define Py_PYFPE_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
/*
7+
---------------------------------------------------------------------
8+
/ Copyright (c) 1996. \
9+
| The Regents of the University of California. |
10+
| All rights reserved. |
11+
| |
12+
| Permission to use, copy, modify, and distribute this software for |
13+
| any purpose without fee is hereby granted, provided that this en- |
14+
| tire notice is included in all copies of any software which is or |
15+
| includes a copy or modification of this software and in all |
16+
| copies of the supporting documentation for such software. |
17+
| |
18+
| This work was produced at the University of California, Lawrence |
19+
| Livermore National Laboratory under contract no. W-7405-ENG-48 |
20+
| between the U.S. Department of Energy and The Regents of the |
21+
| University of California for the operation of UC LLNL. |
22+
| |
23+
| DISCLAIMER |
24+
| |
25+
| This software was prepared as an account of work sponsored by an |
26+
| agency of the United States Government. Neither the United States |
27+
| Government nor the University of California nor any of their em- |
28+
| ployees, makes any warranty, express or implied, or assumes any |
29+
| liability or responsibility for the accuracy, completeness, or |
30+
| usefulness of any information, apparatus, product, or process |
31+
| disclosed, or represents that its use would not infringe |
32+
| privately-owned rights. Reference herein to any specific commer- |
33+
| cial products, process, or service by trade name, trademark, |
34+
| manufacturer, or otherwise, does not necessarily constitute or |
35+
| imply its endorsement, recommendation, or favoring by the United |
36+
| States Government or the University of California. The views and |
37+
| opinions of authors expressed herein do not necessarily state or |
38+
| reflect those of the United States Government or the University |
39+
| of California, and shall not be used for advertising or product |
40+
\ endorsement purposes. /
41+
---------------------------------------------------------------------
42+
*/
43+
44+
/*
45+
* Define macros for handling SIGFPE.
46+
* Lee Busby, LLNL, November, 1996
47+
48+
*
49+
*********************************************
50+
* Overview of the system for handling SIGFPE:
51+
*
52+
* This file (Include/pyfpe.h) defines a couple of "wrapper" macros for
53+
* insertion into your Python C code of choice. Their proper use is
54+
* discussed below. The file Python/pyfpe.c defines a pair of global
55+
* variables PyFPE_jbuf and PyFPE_counter which are used by the signal
56+
* handler for SIGFPE to decide if a particular exception was protected
57+
* by the macros. The signal handler itself, and code for enabling the
58+
* generation of SIGFPE in the first place, is in a (new) Python module
59+
* named fpectl. This module is standard in every respect. It can be loaded
60+
* either statically or dynamically as you choose, and like any other
61+
* Python module, has no effect until you import it.
62+
*
63+
* In the general case, there are three steps toward handling SIGFPE in any
64+
* Python code:
65+
*
66+
* 1) Add the *_PROTECT macros to your C code as required to protect
67+
* dangerous floating point sections.
68+
*
69+
* 2) Turn on the inclusion of the code by #defining WANT_SIGFPE_HANDLER in
70+
* config.h.in before you configure, compile, and install Python, and the
71+
* fpectl module, and any other modules which may have conditional code.
72+
*
73+
* 3) When python is built and running, import fpectl, and execute
74+
* fpectl.turnon_sigfpe(). This sets up the signal handler and enables
75+
* generation of SIGFPE whenever an exception occurs. From this point
76+
* on, any properly trapped SIGFPE should result in the Python
77+
* FloatingPointError exception.
78+
*
79+
* Step 1 has been done already for the Python kernel code, and will be
80+
* done soon for Hugunin's NumPy array package and my Gist graphics module.
81+
* Step 2 is usually done once at python install time. Python's behavior
82+
* with respect to SIGFPE is not changed unless you also do step 3. Thus
83+
* you can control this new facility at compile time, or run time, or both.
84+
*
85+
********************************
86+
* Using the macros in your code:
87+
*
88+
* static PyObject *foobar(PyObject *self,PyObject *args)
89+
* {
90+
* ....
91+
* PyFPE_START_PROTECT("Error in foobar", return 0)
92+
* dangerous_op(somearg1, somearg2, ...);
93+
* PyFPE_END_PROTECT
94+
* ....
95+
* }
96+
*
97+
* If a floating point error occurs in dangerous_op, foobar returns 0
98+
* (NULL), after setting the associated value of the FloatingPointError
99+
* exception to "Error in foobar". ``Dangerous_op'' can be a single
100+
* operation, or a block, or function calls, or any combination, so long as
101+
* no alternate return is possible before the PyFPE_END_PROTECT macro is
102+
* reached.
103+
*
104+
* The macros can only be used in a function context where an error return
105+
* can be recognized as signaling a Python exception. (Generally, most
106+
* functions that return a PyObject * will qualify.)
107+
*
108+
* Guido's original design suggestion for PyFPE_START_PROTECT and
109+
* PyFPE_END_PROTECT had them open and close a local block, with a locally
110+
* defined jmp_buf and jmp_buf pointer. This would allow recursive nesting
111+
* of the macros. The Ansi C standard makes it clear that such local
112+
* variables need to be declared with the "volatile" type qualifier to keep
113+
* setjmp from corrupting their values. Some current implementations seem
114+
* to be more restrictive. For example, the HPUX man page for setjmp says
115+
*
116+
* Upon the return from a setjmp() call caused by a longjmp(), the
117+
* values of any non-static local variables belonging to the routine
118+
* from which setjmp() was called are undefined. Code which depends on
119+
* such values is not guaranteed to be portable.
120+
*
121+
* I therefore decided on a more limited form of nesting, using a counter
122+
* variable (PyFPE_counter) to keep track of any recursion. If an exception
123+
* occurs in an ``inner'' pair of macros, the return will apparently
124+
* come from the top level.
125+
*
126+
*/
127+
128+
#ifdef WANT_SIGFPE_HANDLER
129+
#include <signal.h>
130+
#include <setjmp.h>
131+
#include <math.h>
132+
extern jmp_buf PyFPE_jbuf;
133+
extern int PyFPE_counter;
134+
extern double PyFPE_dummy(void);
135+
136+
#define PyFPE_START_PROTECT(err_string, leave_stmt) \
137+
if (!PyFPE_counter++ && setjmp(PyFPE_jbuf)) { \
138+
PyFPE_counter = 0; \
139+
PyErr_SetString(PyExc_FloatingPointError, err_string); \
140+
leave_stmt; \
141+
}
142+
143+
/*
144+
* This (following) is a heck of a way to decrement a counter. However,
145+
* code optimizers will sometimes move this statement so that it gets
146+
* executed *before* the unsafe expression which we're trying to protect.
147+
* This pretty well messes things up, of course. So the best I've been able
148+
* to do is to put a (hopefully fast) function call into the expression
149+
* which counts down PyFPE_counter, and thereby monkey wrench the overeager
150+
* optimizer. Better solutions are welcomed....
151+
*/
152+
#define PyFPE_END_PROTECT PyFPE_counter -= (int)PyFPE_dummy();
153+
154+
#else
155+
156+
#define PyFPE_START_PROTECT(err_string, leave_stmt)
157+
#define PyFPE_END_PROTECT
158+
159+
#endif
160+
161+
#ifdef __cplusplus
162+
}
163+
#endif
164+
#endif /* !Py_PYFPE_H */

Include/rename2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ PERFORMANCE OF THIS SOFTWARE.
7575
#define AttributeError PyExc_AttributeError
7676
#define ConflictError PyExc_ConflictError
7777
#define EOFError PyExc_EOFError
78+
#define FloatingPointError PyExc_FloatingPointError
7879
#define IOError PyExc_IOError
7980
#define ImportError PyExc_ImportError
8081
#define IndexError PyExc_IndexError

0 commit comments

Comments
 (0)