summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2007-10-21 03:22:55 +0000
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2007-10-21 03:22:55 +0000
commite1dd9ca8431e5a36c070fcfbdd94c8c0db0a3dc2 (patch)
tree70d0ec254a17dc990f82a3e1b2ab01ace83fc463
parent63773ad1e0e60addb540475560e10dfaeda8796b (diff)
downloadpsycopg2-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--ChangeLog7
-rw-r--r--psycopg/psycopg.h2
-rw-r--r--psycopg/psycopgmodule.c64
-rw-r--r--psycopg/typecast_basic.c3
4 files changed, 66 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 8a48e92..302bb5b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;