]> granicus.if.org Git - python/commitdiff
Add a bunch of GIL release/acquire points in tp_print implementations and for
authorBrett Cannon <bcannon@gmail.com>
Mon, 17 Sep 2007 03:28:34 +0000 (03:28 +0000)
committerBrett Cannon <bcannon@gmail.com>
Mon, 17 Sep 2007 03:28:34 +0000 (03:28 +0000)
PyObject_Print().

Closes issue #1164.

13 files changed:
Misc/NEWS
Modules/_collectionsmodule.c
Objects/boolobject.c
Objects/complexobject.c
Objects/dictobject.c
Objects/fileobject.c
Objects/floatobject.c
Objects/intobject.c
Objects/listobject.c
Objects/object.c
Objects/setobject.c
Objects/stringobject.c
Objects/tupleobject.c

index 73495db1e52b83c2232ea70879c03d9248008d2c..e3869d971d316b2e9fb38fa59ab53bb4a3c0dd50 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,11 @@ What's New in Python 2.6 alpha 1?
 Core and builtins
 -----------------
 
+- Issue #1164: It was possible to trigger deadlock when using the 'print'
+  statement to write to a file since the GIL was not released as needed.  Now
+  PyObject_Print() does the right thing along with various tp_print
+  implementations of the built-in types and those in the collections module.
+
 - Issue #1147: Exceptions were directly allowing string exceptions in their
   throw() method even though string exceptions no longer allowed.
 
index 7f5e2aed6990640a8c7f13f869ff5e1596472c81..ea68f80ad9639ab5a835522bc667cad572d0b95b 100644 (file)
@@ -652,7 +652,9 @@ deque_tp_print(PyObject *deque, FILE *fp, int flags)
        if (i != 0) {
                if (i < 0)
                        return i;
+               Py_BEGIN_ALLOW_THREADS
                fputs("[...]", fp);
+               Py_END_ALLOW_THREADS
                return 0;
        }
 
@@ -660,9 +662,13 @@ deque_tp_print(PyObject *deque, FILE *fp, int flags)
        if (it == NULL)
                return -1;
 
+       Py_BEGIN_ALLOW_THREADS
        fputs("deque([", fp);
+       Py_END_ALLOW_THREADS
        while ((item = PyIter_Next(it)) != NULL) {
+               Py_BEGIN_ALLOW_THREADS
                fputs(emit, fp);
+               Py_END_ALLOW_THREADS
                emit = separator;
                if (PyObject_Print(item, fp, 0) != 0) {
                        Py_DECREF(item);
@@ -676,7 +682,9 @@ deque_tp_print(PyObject *deque, FILE *fp, int flags)
        Py_DECREF(it);
        if (PyErr_Occurred())
                return -1;
+       Py_BEGIN_ALLOW_THREADS
        fputs("])", fp);
+       Py_END_ALLOW_THREADS
        return 0;
 }
 
@@ -1190,15 +1198,24 @@ static int
 defdict_print(defdictobject *dd, FILE *fp, int flags)
 {
        int sts;
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, "defaultdict(");
-       if (dd->default_factory == NULL)
+       Py_END_ALLOW_THREADS
+       if (dd->default_factory == NULL) {
+               Py_BEGIN_ALLOW_THREADS
                fprintf(fp, "None");
+               Py_END_ALLOW_THREADS
+       }
        else {
                PyObject_Print(dd->default_factory, fp, 0);
        }
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, ", ");
+       Py_END_ALLOW_THREADS
        sts = PyDict_Type.tp_print((PyObject *)dd, fp, 0);
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, ")");
+       Py_END_ALLOW_THREADS
        return sts;
 }
 
index 40f860bb4da90910d246bece6e7eb8840f7e70f2..fd73d2809535db429c1452f3fb37d33d7b087368 100644 (file)
@@ -7,7 +7,9 @@
 static int
 bool_print(PyBoolObject *self, FILE *fp, int flags)
 {
+       Py_BEGIN_ALLOW_THREADS
        fputs(self->ob_ival == 0 ? "False" : "True", fp);
+       Py_END_ALLOW_THREADS
        return 0;
 }
 
index 6d1dbded2c298195c3a7ab4d5ed88f0d0d341db8..7de4d5ce604b39382a8ca7d00a7f00c172888def 100644 (file)
@@ -341,7 +341,9 @@ complex_print(PyComplexObject *v, FILE *fp, int flags)
        char buf[100];
        complex_to_buf(buf, sizeof(buf), v,
                       (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
+       Py_BEGIN_ALLOW_THREADS
        fputs(buf, fp);
+       Py_END_ALLOW_THREADS
        return 0;
 }
 
index 30b35980bd615b2ac2c13b1701326ff41909dc4f..aa61e8c5eb9bfb3b93abd60badd93cfc424108ba 100644 (file)
@@ -867,11 +867,15 @@ dict_print(register dictobject *mp, register FILE *fp, register int flags)
        if (status != 0) {
                if (status < 0)
                        return status;
+               Py_BEGIN_ALLOW_THREADS
                fprintf(fp, "{...}");
+               Py_END_ALLOW_THREADS
                return 0;
        }
 
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, "{");
+       Py_END_ALLOW_THREADS
        any = 0;
        for (i = 0; i <= mp->ma_mask; i++) {
                dictentry *ep = mp->ma_table + i;
@@ -880,14 +884,19 @@ dict_print(register dictobject *mp, register FILE *fp, register int flags)
                        /* Prevent PyObject_Repr from deleting value during
                           key format */
                        Py_INCREF(pvalue);
-                       if (any++ > 0)
+                       if (any++ > 0) {
+                               Py_BEGIN_ALLOW_THREADS
                                fprintf(fp, ", ");
+                               Py_END_ALLOW_THREADS
+                       }
                        if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) {
                                Py_DECREF(pvalue);
                                Py_ReprLeave((PyObject*)mp);
                                return -1;
                        }
+                       Py_BEGIN_ALLOW_THREADS
                        fprintf(fp, ": ");
+                       Py_END_ALLOW_THREADS
                        if (PyObject_Print(pvalue, fp, 0) != 0) {
                                Py_DECREF(pvalue);
                                Py_ReprLeave((PyObject*)mp);
@@ -896,7 +905,9 @@ dict_print(register dictobject *mp, register FILE *fp, register int flags)
                        Py_DECREF(pvalue);
                }
        }
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, "}");
+       Py_END_ALLOW_THREADS
        Py_ReprLeave((PyObject*)mp);
        return 0;
 }
index 4c5b37d2f6a8eb06e68be964d74583b7475de030..16786f87edaecea7f57da7789f886e9ec9c2a1f2 100644 (file)
@@ -2241,7 +2241,9 @@ PyFile_WriteString(const char *s, PyObject *f)
                        err_closed();
                        return -1;
                }
+               Py_BEGIN_ALLOW_THREADS
                fputs(s, fp);
+               Py_END_ALLOW_THREADS
                return 0;
        }
        else if (!PyErr_Occurred()) {
index 4dd7d03190676dcc159d249ef76e0cbc16e2f77c..bf9b1728621ee5ce1677b0810707ca12e33ffdbc 100644 (file)
@@ -334,7 +334,9 @@ float_print(PyFloatObject *v, FILE *fp, int flags)
        char buf[100];
        format_float(buf, sizeof(buf), v,
                     (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
+       Py_BEGIN_ALLOW_THREADS
        fputs(buf, fp);
+       Py_END_ALLOW_THREADS
        return 0;
 }
 
index c4aeed5ebd9b8da5fa6d3c290674395a9d0f8db3..364947eb9faab11f4c240aef30c187eb2075420f 100644 (file)
@@ -425,7 +425,10 @@ static int
 int_print(PyIntObject *v, FILE *fp, int flags)
      /* flags -- not used but required by interface */
 {
-       fprintf(fp, "%ld", v->ob_ival);
+       long int_val = v->ob_ival;
+       Py_BEGIN_ALLOW_THREADS
+       fprintf(fp, "%ld", int_val);
+       Py_END_ALLOW_THREADS
        return 0;
 }
 
index 92bad8c7c84afb80967c6abf61e7a37efa61f1e6..a3fa983c59b2f7d08cda55f774422f8640842f80 100644 (file)
@@ -282,19 +282,28 @@ list_print(PyListObject *op, FILE *fp, int flags)
        if (rc != 0) {
                if (rc < 0)
                        return rc;
+               Py_BEGIN_ALLOW_THREADS
                fprintf(fp, "[...]");
+               Py_END_ALLOW_THREADS
                return 0;
        }
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, "[");
+       Py_END_ALLOW_THREADS
        for (i = 0; i < Py_Size(op); i++) {
-               if (i > 0)
+               if (i > 0) {
+                       Py_BEGIN_ALLOW_THREADS
                        fprintf(fp, ", ");
+                       Py_END_ALLOW_THREADS
+               }
                if (PyObject_Print(op->ob_item[i], fp, 0) != 0) {
                        Py_ReprLeave((PyObject *)op);
                        return -1;
                }
        }
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, "]");
+       Py_END_ALLOW_THREADS
        Py_ReprLeave((PyObject *)op);
        return 0;
 }
index 4330b0803c2f12c095f7e6240f490fe978475236..0651d6b6d87bc5df54d9ffccecdc1b2236b18a24 100644 (file)
@@ -279,14 +279,18 @@ internal_print(PyObject *op, FILE *fp, int flags, int nesting)
 #endif
        clearerr(fp); /* Clear any previous error condition */
        if (op == NULL) {
+               Py_BEGIN_ALLOW_THREADS
                fprintf(fp, "<nil>");
+               Py_END_ALLOW_THREADS
        }
        else {
                if (op->ob_refcnt <= 0)
                        /* XXX(twouters) cast refcount to long until %zd is
                           universally available */
+                       Py_BEGIN_ALLOW_THREADS
                        fprintf(fp, "<refcnt %ld at %p>",
                                (long)op->ob_refcnt, op);
+                       Py_END_ALLOW_THREADS
                else if (Py_Type(op)->tp_print == NULL) {
                        PyObject *s;
                        if (flags & Py_PRINT_RAW)
index f0a11caecb01ecddb2d8833a38f28d50f934404d..025a79b6dcba8e6a81ccc1628f3ba95cc491a810 100644 (file)
@@ -577,20 +577,28 @@ set_tp_print(PySetObject *so, FILE *fp, int flags)
        if (status != 0) {
                if (status < 0)
                        return status;
+               Py_BEGIN_ALLOW_THREADS
                fprintf(fp, "%s(...)", so->ob_type->tp_name);
+               Py_END_ALLOW_THREADS
                return 0;
        }        
 
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, "%s([", so->ob_type->tp_name);
+       Py_END_ALLOW_THREADS
        while (set_next(so, &pos, &entry)) {
+               Py_BEGIN_ALLOW_THREADS
                fputs(emit, fp);
+               Py_END_ALLOW_THREADS
                emit = separator;
                if (PyObject_Print(entry->key, fp, 0) != 0) {
                        Py_ReprLeave((PyObject*)so);
                        return -1;
                }
        }
+       Py_BEGIN_ALLOW_THREADS
        fputs("])", fp);
+       Py_END_ALLOW_THREADS
        Py_ReprLeave((PyObject*)so);        
        return 0;
 }
index fb7548d33f73bb54aa9b140a0e991d6f7305e360..22b50d5f76d0aaa8c33c947debdbdc475b098464 100644 (file)
@@ -788,7 +788,7 @@ PyString_AsStringAndSize(register PyObject *obj,
 static int
 string_print(PyStringObject *op, FILE *fp, int flags)
 {
-       Py_ssize_t i;
+       Py_ssize_t i, str_len;
        char c;
        int quote;
 
@@ -806,6 +806,7 @@ string_print(PyStringObject *op, FILE *fp, int flags)
        if (flags & Py_PRINT_RAW) {
                char *data = op->ob_sval;
                Py_ssize_t size = Py_Size(op);
+               Py_BEGIN_ALLOW_THREADS
                while (size > INT_MAX) {
                        /* Very long strings cannot be written atomically.
                         * But don't write exactly INT_MAX bytes at a time
@@ -821,6 +822,7 @@ string_print(PyStringObject *op, FILE *fp, int flags)
 #else
                 fwrite(data, 1, (int)size, fp);
 #endif
+               Py_END_ALLOW_THREADS
                return 0;
        }
 
@@ -830,8 +832,13 @@ string_print(PyStringObject *op, FILE *fp, int flags)
            !memchr(op->ob_sval, '"', Py_Size(op)))
                quote = '"';
 
+       str_len = Py_Size(op);
+       Py_BEGIN_ALLOW_THREADS
        fputc(quote, fp);
-       for (i = 0; i < Py_Size(op); i++) {
+       for (i = 0; i < str_len; i++) {
+               /* Since strings are immutable and the caller should have a
+               reference, accessing the interal buffer should not be an issue
+               with the GIL released. */
                c = op->ob_sval[i];
                if (c == quote || c == '\\')
                        fprintf(fp, "\\%c", c);
@@ -847,6 +854,7 @@ string_print(PyStringObject *op, FILE *fp, int flags)
                        fputc(c, fp);
        }
        fputc(quote, fp);
+       Py_END_ALLOW_THREADS
        return 0;
 }
 
index f1e3aeeee761fea8d02cb3c2c5d1b6d8eabacb5d..b85762a743457e2e5a65969d9e9b169f8b055720 100644 (file)
@@ -188,16 +188,24 @@ static int
 tupleprint(PyTupleObject *op, FILE *fp, int flags)
 {
        Py_ssize_t i;
+       Py_BEGIN_ALLOW_THREADS
        fprintf(fp, "(");
+       Py_END_ALLOW_THREADS
        for (i = 0; i < Py_Size(op); i++) {
-               if (i > 0)
+               if (i > 0) {
+                       Py_BEGIN_ALLOW_THREADS
                        fprintf(fp, ", ");
+                       Py_END_ALLOW_THREADS
+               }
                if (PyObject_Print(op->ob_item[i], fp, 0) != 0)
                        return -1;
        }
-       if (Py_Size(op) == 1)
+       i = Py_Size(op);
+       Py_BEGIN_ALLOW_THREADS
+       if (i == 1)
                fprintf(fp, ",");
        fprintf(fp, ")");
+       Py_END_ALLOW_THREADS
        return 0;
 }