diff options
| author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2007-10-21 03:22:55 +0000 |
|---|---|---|
| committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2007-10-21 03:22:55 +0000 |
| commit | e1dd9ca8431e5a36c070fcfbdd94c8c0db0a3dc2 (patch) | |
| tree | 70d0ec254a17dc990f82a3e1b2ab01ace83fc463 | |
| parent | 63773ad1e0e60addb540475560e10dfaeda8796b (diff) | |
| download | psycopg2-e1dd9ca8431e5a36c070fcfbdd94c8c0db0a3dc2.tar.gz | |
Fixed bug #192 (Decimal support not safe for use with multiple sub
interpreters) as proposed by Graham Dumpleton.
If running in the main interpreter, use a cached version of the Decimal
object. Else repeat the object lookup.
| -rw-r--r-- | ChangeLog | 7 | ||||
| -rw-r--r-- | psycopg/psycopg.h | 2 | ||||
| -rw-r--r-- | psycopg/psycopgmodule.c | 64 | ||||
| -rw-r--r-- | psycopg/typecast_basic.c | 3 |
4 files changed, 66 insertions, 10 deletions
@@ -1,4 +1,9 @@ -2007-09-08 Federico Di Gregorio <fog@initd.org> +2007-10-21 Daniele Varrazzo <daniele.varrazzo@gmail.com> + + * Fixed bug #192 (Decimal support not safe for use with multiple sub + interpreters) as proposed by Graham Dumpleton. + +2007-09-08 Federico Di Gregorio <fog@initd.org> * Added MonoDevelop project, yahi! diff --git a/psycopg/psycopg.h b/psycopg/psycopg.h index aeb174c..945ce92 100644 --- a/psycopg/psycopg.h +++ b/psycopg/psycopg.h @@ -130,7 +130,7 @@ typedef struct { } encodingPair; /* the Decimal type, used by the DECIMAL typecaster */ -extern PyObject *decimalType; +extern PyObject *psyco_GetDecimalType(void); /* some utility functions */ extern void psyco_set_error(PyObject *exc, PyObject *curs, char *msg, diff --git a/psycopg/psycopgmodule.c b/psycopg/psycopgmodule.c index ee4bc8e..53fd641 100644 --- a/psycopg/psycopgmodule.c +++ b/psycopg/psycopgmodule.c @@ -62,7 +62,6 @@ PyObject *pyPsycopgTzLOCAL = NULL; PyObject *pyPsycopgTzFixedOffsetTimezone = NULL; PyObject *psycoEncodings = NULL; -PyObject *decimalType = NULL; /** connect module-level function **/ #define psyco_connect_doc \ @@ -330,7 +329,8 @@ psyco_adapters_init(PyObject *mod) #endif #ifdef HAVE_DECIMAL - microprotocols_add((PyTypeObject*)decimalType, NULL, (PyObject*)&asisType); + microprotocols_add((PyTypeObject*)psyco_GetDecimalType(), + NULL, (PyObject*)&asisType); #endif } @@ -554,14 +554,55 @@ psyco_set_error(PyObject *exc, PyObject *curs, char *msg, } } -/* psyco_decimal_init - Initialize the module's pointer to the decimal type. */ +/* Return nonzero if the current one is the main interpreter */ +static int +psyco_is_main_interp() +{ + static PyInterpreterState *main_interp = NULL; /* Cached reference */ + PyInterpreterState *interp; -void -psyco_decimal_init(void) + if (main_interp) { + return (main_interp == PyThreadState_Get()->interp); + } + + /* No cached value: cache the proper value and try again. */ + interp = PyInterpreterState_Head(); + while (interp->next) + interp = interp->next; + + main_interp = interp; + assert (main_interp); + return psyco_is_main_interp(); +} + + +/* psyco_GetDecimalType + + Return a new reference to the adapter for decimal type. + + If decimals should be used but the module import fails, fall back on + the float type. + + If decimals are not to be used, return NULL. + */ + +PyObject * +psyco_GetDecimalType(void) { + PyObject *decimalType = NULL; + static PyObject *cachedType = NULL; + #ifdef HAVE_DECIMAL + + /* Use the cached object if running from the main interpreter. */ + int can_cache = psyco_is_main_interp(); + if (can_cache && cachedType) { + Py_INCREF(cachedType); + return cachedType; + } + + /* Get a new reference to the Decimal type. */ PyObject *decimal = PyImport_ImportModule("decimal"); if (decimal) { decimalType = PyObject_GetAttrString(decimal, "Decimal"); @@ -572,7 +613,15 @@ psyco_decimal_init(void) decimalType = (PyObject *)&PyFloat_Type; Py_INCREF(decimalType); } -#endif + + /* Store the object from future uses. */ + if (can_cache && !cachedType) { + cachedType = decimalType; + } + +#endif /* HAVE_DECIMAL */ + + return decimalType; } @@ -731,7 +780,6 @@ init_psycopg(void) /* other mixed initializations of module-level variables */ psycoEncodings = PyDict_New(); psyco_encodings_fill(psycoEncodings); - psyco_decimal_init(); /* set some module's parameters */ PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION); diff --git a/psycopg/typecast_basic.c b/psycopg/typecast_basic.c index 2bc9718..eeb96be 100644 --- a/psycopg/typecast_basic.c +++ b/psycopg/typecast_basic.c @@ -120,6 +120,7 @@ static PyObject * typecast_DECIMAL_cast(char *s, Py_ssize_t len, PyObject *curs) { PyObject *res = NULL; + PyObject *decimalType; char *buffer; if (s == NULL) {Py_INCREF(Py_None); return Py_None;} @@ -127,7 +128,9 @@ typecast_DECIMAL_cast(char *s, Py_ssize_t len, PyObject *curs) if ((buffer = PyMem_Malloc(len+1)) == NULL) return PyErr_NoMemory(); strncpy(buffer, s, (size_t) len); buffer[len] = '\0'; + decimalType = psyco_GetDecimalType(); res = PyObject_CallFunction(decimalType, "s", buffer); + Py_DECREF(decimalType); PyMem_Free(buffer); return res; |
