summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1997-02-14 22:59:58 (GMT)
committerGuido van Rossum <guido@python.org>1997-02-14 22:59:58 (GMT)
commit52fa3a69090ac098b01b28f397d9bd08f957e8cd (patch)
treec01e3347c776bd8f5deb93af7e90cfca37dea8eb
parent0ae748d3c409fc4b870baadd601a53c6a43ddf11 (diff)
downloadcpython-52fa3a69090ac098b01b28f397d9bd08f957e8cd.zip
cpython-52fa3a69090ac098b01b28f397d9bd08f957e8cd.tar.gz
cpython-52fa3a69090ac098b01b28f397d9bd08f957e8cd.tar.bz2
Changes for Lee Busby's SIGFPE patch set.
Two new modules fpectl and fpetest. Surround various and sundry f.p. operations with PyFPE_*_PROTECT macros.
-rw-r--r--Modules/_tkinter.c6
-rw-r--r--Modules/cmathmodule.c2
-rw-r--r--Modules/fpectlmodule.c244
-rw-r--r--Modules/fpetestmodule.c228
-rw-r--r--Modules/imgfile.c2
-rw-r--r--Modules/mathmodule.c6
-rw-r--r--Modules/mpzmodule.c3
-rw-r--r--Modules/stropmodule.c2
8 files changed, 492 insertions, 1 deletions
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index ba95310..33d5392 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -724,10 +724,14 @@ Tkapp_ExprDouble (self, args)
{
char *s;
double v;
+ int retval;
if (!PyArg_Parse(args, "s", &s))
return NULL;
- if (Tcl_ExprDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
+ PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
+ retval = Tcl_ExprDouble (Tkapp_Interp (self), s, &v);
+ PyFPE_END_PROTECT
+ if (retval == TCL_ERROR)
return Tkinter_Error(self);
return Py_BuildValue("d", v);
}
diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c
index 7e9de1f..438f010 100644
--- a/Modules/cmathmodule.c
+++ b/Modules/cmathmodule.c
@@ -247,7 +247,9 @@ math_1(args, func)
if (!PyArg_ParseTuple(args, "D", &x))
return NULL;
errno = 0;
+ PyFPE_START_PROTECT("complex function", return 0)
x = (*func)(x);
+ PyFPE_END_PROTECT
CHECK(x.real);
CHECK(x.imag);
if (errno != 0)
diff --git a/Modules/fpectlmodule.c b/Modules/fpectlmodule.c
new file mode 100644
index 0000000..3fc5d06
--- /dev/null
+++ b/Modules/fpectlmodule.c
@@ -0,0 +1,244 @@
+/*
+ ---------------------------------------------------------------------
+ / Copyright (c) 1996. \
+ | The Regents of the University of California. |
+ | All rights reserved. |
+ | |
+ | Permission to use, copy, modify, and distribute this software for |
+ | any purpose without fee is hereby granted, provided that this en- |
+ | tire notice is included in all copies of any software which is or |
+ | includes a copy or modification of this software and in all |
+ | copies of the supporting documentation for such software. |
+ | |
+ | This work was produced at the University of California, Lawrence |
+ | Livermore National Laboratory under contract no. W-7405-ENG-48 |
+ | between the U.S. Department of Energy and The Regents of the |
+ | University of California for the operation of UC LLNL. |
+ | |
+ | DISCLAIMER |
+ | |
+ | This software was prepared as an account of work sponsored by an |
+ | agency of the United States Government. Neither the United States |
+ | Government nor the University of California nor any of their em- |
+ | ployees, makes any warranty, express or implied, or assumes any |
+ | liability or responsibility for the accuracy, completeness, or |
+ | usefulness of any information, apparatus, product, or process |
+ | disclosed, or represents that its use would not infringe |
+ | privately-owned rights. Reference herein to any specific commer- |
+ | cial products, process, or service by trade name, trademark, |
+ | manufacturer, or otherwise, does not necessarily constitute or |
+ | imply its endorsement, recommendation, or favoring by the United |
+ | States Government or the University of California. The views and |
+ | opinions of authors expressed herein do not necessarily state or |
+ | reflect those of the United States Government or the University |
+ | of California, and shall not be used for advertising or product |
+ \ endorsement purposes. /
+ ---------------------------------------------------------------------
+*/
+
+/*
+ Floating point exception control module.
+
+ This Python module provides bare-bones control over floating point
+ units from several hardware manufacturers. Specifically, it allows
+ the user to turn on the generation of SIGFPE whenever any of the
+ three serious IEEE 754 exceptions (Division by Zero, Overflow,
+ Invalid Operation) occurs. We currently ignore Underflow and
+ Inexact Result exceptions, although those could certainly be added
+ if desired.
+
+ The module also establishes a signal handler for SIGFPE during
+ initialization. This builds on code found in the Python
+ distribution at Include/pyfpe.h and Python/pyfpe.c. If those files
+ are not in your Python distribution, find them in a patch at
+ ftp://icf.llnl.gov/pub/python/busby/patches.961108.tgz.
+
+ This module is only useful to you if it happens to include code
+ specific for your hardware and software environment. If you can
+ contribute OS-specific code for new platforms, or corrections for
+ the code provided, it will be greatly appreciated.
+
+ ** Version 1.0: September 20, 1996. Lee Busby, LLNL.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "Python.h"
+#include <signal.h>
+
+#ifndef WANT_SIGFPE_HANDLER
+/* Define locally if they are not defined in Python. This gives only
+ * the limited control to induce a core dump in case of an exception.
+ */
+static jmp_buf PyFPE_jbuf;
+static int PyFPE_counter = 0;
+#endif
+
+typedef RETSIGTYPE Sigfunc(int);
+static Sigfunc sigfpe_handler;
+static void fpe_reset(Sigfunc *);
+
+static PyObject *fpe_error;
+void initfpectl(void);
+static PyObject *turnon_sigfpe (PyObject *self,PyObject *args);
+static PyObject *turnoff_sigfpe (PyObject *self,PyObject *args);
+
+static PyMethodDef fpectl_methods[] = {
+ {"turnon_sigfpe", (PyCFunction) turnon_sigfpe, 1},
+ {"turnoff_sigfpe", (PyCFunction) turnoff_sigfpe, 1},
+ {0,0}
+};
+
+static PyObject *turnon_sigfpe(PyObject *self,PyObject *args)
+{
+ /* Do any architecture-specific one-time only initialization here. */
+
+ fpe_reset(sigfpe_handler);
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+static void fpe_reset(Sigfunc *handler)
+{
+ /* Reset the exception handling machinery, and reset the signal
+ * handler for SIGFPE to the given handler.
+ */
+
+/*-- IRIX -----------------------------------------------------------------*/
+#if defined(sgi)
+ /* See man page on handle_sigfpes -- must link with -lfpe
+ * My usage doesn't follow the man page exactly. Maybe somebody
+ * else can explain handle_sigfpes to me....
+ * cc -c -I/usr/local/python/include fpectlmodule.c
+ * ld -shared -o fpectlmodule.so fpectlmodule.o -lfpe
+ */
+#include <sigfpe.h>
+ typedef void user_routine (unsigned[5], int[2]);
+ typedef void abort_routine (unsigned long);
+ handle_sigfpes(_OFF, 0,
+ (user_routine *)0,
+ _TURN_OFF_HANDLER_ON_ERROR,
+ (abort_routine*)0);
+ handle_sigfpes(_ON, _EN_OVERFL | _EN_DIVZERO | _EN_INVALID,
+ (user_routine *)0,
+ _ABORT_ON_ERROR,
+ (abort_routine*)0);
+ signal(SIGFPE, handler);
+
+/*-- SunOS and Solaris ----------------------------------------------------*/
+#elif defined(sun)
+ /* References: ieee_handler, ieee_sun, ieee_functions, and ieee_flags
+ man pages (SunOS or Solaris)
+ cc -c -I/usr/local/python/include fpectlmodule.c
+ ld -G -o fpectlmodule.so -L/opt/SUNWspro/lib fpectlmodule.o -lsunmath -lm
+ */
+#include <math.h>
+ char *mode="exception", *in="all", *out;
+ (void) nonstandard_arithmetic();
+ (void) ieee_flags("clearall",mode,in,&out);
+ (void) ieee_handler("set","common",(sigfpe_handler_type)handler);
+ signal(SIGFPE, handler);
+
+/*-- HPUX -----------------------------------------------------------------*/
+#elif defined(__hppa) || defined(hppa)
+ /* References: fpsetmask man page */
+ /* cc -Aa +z -c -I/usr/local/python/include fpectlmodule.c */
+ /* ld -b -o fpectlmodule.sl fpectlmodule.o -lm */
+#include <math.h>
+ fpsetdefaults();
+ signal(SIGFPE, handler);
+
+/*-- IBM AIX --------------------------------------------------------------*/
+#elif defined(__AIX) || defined(_AIX)
+ /* References: fp_trap, fp_enable man pages */
+#include <fptrap.h>
+ fp_trap(FP_TRAP_SYNC);
+ fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
+ signal(SIGFPE, handler);
+
+/*-- DEC ALPHA OSF --------------------------------------------------------*/
+#elif defined(__alpha)
+ /* References: exception_intro, ieee man pages */
+ /* cc -c -I/usr/local/python/include fpectlmodule.c */
+ /* ld -shared -o fpectlmodule.so fpectlmodule.o */
+#include <machine/fpu.h>
+ unsigned long fp_control =
+ IEEE_TRAP_ENABLE_INV | IEEE_TRAP_ENABLE_DZE | IEEE_TRAP_ENABLE_OVF;
+ ieee_set_fp_control(fp_control);
+ signal(SIGFPE, handler);
+
+/*-- Cray Unicos ----------------------------------------------------------*/
+#elif defined(cray)
+ /* UNICOS delivers SIGFPE by default, but no matherr */
+#ifdef HAS_LIBMSET
+ libmset(-1);
+#endif
+ signal(SIGFPE, handler);
+
+/*-- Linux ----------------------------------------------------------------*/
+#elif defined(linux)
+ /* Linux delivers SIGFPE by default,
+ except for log(0), atanh(-1), 0.^0.
+ */
+ signal(SIGFPE, handler);
+
+/*-- NeXT -----------------------------------------------------------------*/
+#elif defined(NeXT) && defined(m68k) && defined(__GNUC__)
+ /* NeXT needs explicit csr set to generate SIGFPE */
+ asm("fmovel #0x1400,fpcr"); /* set OVFL and ZD bits */
+ signal(SIGFPE, handler);
+
+/*-- Microsoft Windows, NT ------------------------------------------------*/
+#elif defined(_MSC_VER)
+ /* Reference: Visual C++ Books Online 4.2,
+ Run-Time Library Reference, _control87, _controlfp */
+#include <float.h>
+ unsigned int cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW;
+ (void)_controlfp(0, cw);
+ signal(SIGFPE, handler);
+
+/*-- Give Up --------------------------------------------------------------*/
+#else
+ fputs("Operation not implemented\n", stderr);
+#endif
+
+}
+
+static PyObject *turnoff_sigfpe(PyObject *self,PyObject *args)
+{
+ fputs("Operation not implemented\n", stderr);
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+static void sigfpe_handler(int signo)
+{
+ fpe_reset(sigfpe_handler);
+ if(PyFPE_counter) {
+ longjmp(PyFPE_jbuf, 1);
+ } else {
+ Py_FatalError("Unprotected floating point exception");
+ }
+}
+
+void initfpectl(void)
+{
+ PyObject *m, *d;
+ static int already_initialized = 0;
+
+ if (already_initialized) return;
+ m = Py_InitModule("fpectl", fpectl_methods);
+ d = PyModule_GetDict(m);
+ fpe_error = PyString_FromString("fpectl.error");
+ PyDict_SetItemString(d, "error", fpe_error);
+
+ if (PyErr_Occurred())
+ Py_FatalError("Cannot initialize module fpectl");
+ already_initialized = 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Modules/fpetestmodule.c b/Modules/fpetestmodule.c
new file mode 100644
index 0000000..2156afb
--- /dev/null
+++ b/Modules/fpetestmodule.c
@@ -0,0 +1,228 @@
+/*
+ ---------------------------------------------------------------------
+ / Copyright (c) 1996. \
+ | The Regents of the University of California. |
+ | All rights reserved. |
+ | |
+ | Permission to use, copy, modify, and distribute this software for |
+ | any purpose without fee is hereby granted, provided that this en- |
+ | tire notice is included in all copies of any software which is or |
+ | includes a copy or modification of this software and in all |
+ | copies of the supporting documentation for such software. |
+ | |
+ | This work was produced at the University of California, Lawrence |
+ | Livermore National Laboratory under contract no. W-7405-ENG-48 |
+ | between the U.S. Department of Energy and The Regents of the |
+ | University of California for the operation of UC LLNL. |
+ | |
+ | DISCLAIMER |
+ | |
+ | This software was prepared as an account of work sponsored by an |
+ | agency of the United States Government. Neither the United States |
+ | Government nor the University of California nor any of their em- |
+ | ployees, makes any warranty, express or implied, or assumes any |
+ | liability or responsibility for the accuracy, completeness, or |
+ | usefulness of any information, apparatus, product, or process |
+ | disclosed, or represents that its use would not infringe |
+ | privately-owned rights. Reference herein to any specific commer- |
+ | cial products, process, or service by trade name, trademark, |
+ | manufacturer, or otherwise, does not necessarily constitute or |
+ | imply its endorsement, recommendation, or favoring by the United |
+ | States Government or the University of California. The views and |
+ | opinions of authors expressed herein do not necessarily state or |
+ | reflect those of the United States Government or the University |
+ | of California, and shall not be used for advertising or product |
+ \ endorsement purposes. /
+ ---------------------------------------------------------------------
+*/
+
+/*
+ Floating point exception test module.
+
+ */
+
+#include "Python.h"
+
+static PyObject *fpe_error;
+void initfpetest(void);
+static PyObject *test(PyObject *self,PyObject *args);
+static int db0(void);
+static int overflow(void);
+static int nest1(double);
+static int nest2(double);
+static double nest3(double);
+
+static PyMethodDef fpetest_methods[] = {
+ {"test", (PyCFunction) test, 1},
+ {0,0}
+};
+
+static PyObject *test(PyObject *self,PyObject *args)
+{
+ int i = 0, r;
+
+ fprintf(stderr,"Test trapping overflow\n");
+ r = overflow();
+ if(r){
+ fprintf(stderr,"(Note: No exception was raised.)\n");
+ PyErr_Clear();
+ }else{
+ fprintf(stderr,"Trapped:: ");
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ i += r;
+
+ fprintf(stderr,"Test trapping division by zero\n");
+ r = db0();
+ if(r){
+ fprintf(stderr,"(Note: No exception was raised.)\n");
+ PyErr_Clear();
+ }else{
+ fprintf(stderr,"Trapped:: ");
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ i += r;
+
+ fprintf(stderr,"Test nested protection zones, outer zone\n");
+ r = nest1(0.0);
+ if(r){
+ fprintf(stderr,"(Note: No exception was raised.)\n");
+ PyErr_Clear();
+ }else{
+ fprintf(stderr,"Trapped:: ");
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ i += r;
+
+ fprintf(stderr,"Test nested protection zones, inner zone\n");
+ fprintf(stderr,"(Note: Return will apparently come from outer zone.)\n");
+ r = nest1(1.0);
+ if(r){
+ fprintf(stderr,"(Note: No exception was raised.)\n");
+ PyErr_Clear();
+ }else{
+ fprintf(stderr,"Trapped:: ");
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ i += r;
+
+ fprintf(stderr,"Test nested protection zones, trailing outer zone\n");
+ r = nest1(2.0);
+ if(r){
+ fprintf(stderr,"(Note: No exception was raised.)\n");
+ PyErr_Clear();
+ }else{
+ fprintf(stderr,"Trapped:: ");
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ i += r;
+
+ fprintf(stderr,"Test nested function calls, prior error\n");
+ r = nest2(0.0);
+ if(r){
+ fprintf(stderr,"(Note: No exception was raised.)\n");
+ PyErr_Clear();
+ }else{
+ fprintf(stderr,"Trapped:: ");
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ i += r;
+
+ fprintf(stderr,"Test nested function calls, interior error\n");
+ r = nest2(1.0);
+ if(r){
+ fprintf(stderr,"(Note: No exception was raised.)\n");
+ PyErr_Clear();
+ }else{
+ fprintf(stderr,"Trapped:: ");
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ i += r;
+
+ fprintf(stderr,"Test nested function calls, trailing error\n");
+ r = nest2(2.0);
+ if(r){
+ fprintf(stderr,"(Note: No exception was raised.)\n");
+ PyErr_Clear();
+ }else{
+ fprintf(stderr,"Trapped:: ");
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ i += r;
+
+ fprintf(stderr,"Number of tests failed: %d\n", i);
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+static int nest1(double x)
+{
+ double a = 1.0;
+ PyFPE_START_PROTECT("Division by zero, outer zone", return 0)
+ a = 1./x;
+ PyFPE_START_PROTECT("Division by zero, inner zone", return 0)
+ a = 1./(1. - x);
+ PyFPE_END_PROTECT
+ a = 1./(2. - x);
+ PyFPE_END_PROTECT
+ return(1);
+}
+
+static int nest2(double x)
+{
+ double a = 1.0;
+ PyFPE_START_PROTECT("Division by zero, prior error", return 0)
+ a = 1./x;
+ a = nest3(x);
+ a = 1./(2. - x);
+ PyFPE_END_PROTECT
+ return(1);
+}
+
+static double nest3(double x)
+{
+ double result;
+ PyFPE_START_PROTECT("Division by zero, nest3 error", return 0)
+ result = 1./(1. - x);
+ PyFPE_END_PROTECT
+ return result;
+}
+
+static int db0(void)
+{
+ double a = 1.0;
+ PyFPE_START_PROTECT("Division by zero", return 0)
+ a = 1./(a - 1.);
+ PyFPE_END_PROTECT
+ return(1);
+}
+
+static int overflow(void)
+{
+ double a, b = 1.e200;
+ PyFPE_START_PROTECT("Overflow", return 0)
+ a = b*b;
+ PyFPE_END_PROTECT
+ return(1);
+}
+
+void initfpetest(void)
+{
+ PyObject *m, *d;
+
+ m = Py_InitModule("fpetest", fpetest_methods);
+ d = PyModule_GetDict(m);
+ fpe_error = PyString_FromString("fpetest.error");
+ PyDict_SetItemString(d, "error", fpe_error);
+
+ if (PyErr_Occurred())
+ Py_FatalError("Cannot initialize module fpetest");
+}
diff --git a/Modules/imgfile.c b/Modules/imgfile.c
index 33266b9..779169d 100644
--- a/Modules/imgfile.c
+++ b/Modules/imgfile.c
@@ -387,8 +387,10 @@ PyObject *args;
iclose(image);
return NULL;
}
+ PyFPE_START_PROTECT("readscaled", return 0)
xfac = (float)xsize/(float)xwtd;
yfac = (float)ysize/(float)ywtd;
+ PyFPE_END_PROTECT
cdatap = PyString_AsString(rv);
idatap = (long *)cdatap;
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index abf1d5b..bb4f1e8 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -80,7 +80,9 @@ math_1(args, func)
if (! PyArg_Parse(args, "d", &x))
return NULL;
errno = 0;
+ PyFPE_START_PROTECT("in math_1", return 0)
x = (*func)(x);
+ PyFPE_END_PROTECT
CHECK(x);
if (errno != 0)
return math_error();
@@ -97,7 +99,9 @@ math_2(args, func)
if (! PyArg_Parse(args, "(dd)", &x, &y))
return NULL;
errno = 0;
+ PyFPE_START_PROTECT("in math_2", return 0)
x = (*func)(x, y);
+ PyFPE_END_PROTECT
CHECK(x);
if (errno != 0)
return math_error();
@@ -173,7 +177,9 @@ math_ldexp(self, args)
if (! PyArg_Parse(args, "(dd)", &x, &y))
return NULL;
errno = 0;
+ PyFPE_START_PROTECT("ldexp", return 0)
x = ldexp(x, (int)y);
+ PyFPE_END_PROTECT
CHECK(x);
if (errno != 0)
return math_error();
diff --git a/Modules/mpzmodule.c b/Modules/mpzmodule.c
index 1f356e1..bf83109 100644
--- a/Modules/mpzmodule.c
+++ b/Modules/mpzmodule.c
@@ -1488,6 +1488,8 @@ mpz_float(self)
/* let those bits come, let those bits go,
e.g. dismantle mpzscratch, build PyFloatObject */
+ /* Can this overflow? Dunno, protect against that possibility. */
+ PyFPE_START_PROTECT("mpz_float", return 0)
x = 0.0;
mulstate = 1.0;
while (i--) {
@@ -1495,6 +1497,7 @@ mpz_float(self)
mulstate *= multiplier;
mpz_div_2exp(&mpzscratch, &mpzscratch, BITS_PER_MP_LIMB);
}
+ PyFPE_END_PROTECT
assert(mpz_cmp_ui(&mpzscratch, (unsigned long int)0) == 0);
mpz_clear(&mpzscratch);
diff --git a/Modules/stropmodule.c b/Modules/stropmodule.c
index cb062ad..8ddf37d 100644
--- a/Modules/stropmodule.c
+++ b/Modules/stropmodule.c
@@ -661,7 +661,9 @@ strop_atof(self, args)
return NULL;
}
errno = 0;
+ PyFPE_START_PROTECT("strop_atof", return 0)
x = strtod(s, &end);
+ PyFPE_END_PROTECT
while (*end && isspace(Py_CHARMASK(*end)))
end++;
if (*end != '\0') {