[Python-checkins] r58176 - in python/trunk: 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

brett.cannon python-checkins at python.org
Mon Sep 17 05:28:35 CEST 2007


Author: brett.cannon
Date: Mon Sep 17 05:28:34 2007
New Revision: 58176

Modified:
   python/trunk/Misc/NEWS
   python/trunk/Modules/_collectionsmodule.c
   python/trunk/Objects/boolobject.c
   python/trunk/Objects/complexobject.c
   python/trunk/Objects/dictobject.c
   python/trunk/Objects/fileobject.c
   python/trunk/Objects/floatobject.c
   python/trunk/Objects/intobject.c
   python/trunk/Objects/listobject.c
   python/trunk/Objects/object.c
   python/trunk/Objects/setobject.c
   python/trunk/Objects/stringobject.c
   python/trunk/Objects/tupleobject.c
Log:
Add a bunch of GIL release/acquire points in tp_print implementations and for
PyObject_Print().

Closes issue #1164.


Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Mon Sep 17 05:28:34 2007
@@ -12,6 +12,11 @@
 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.
 

Modified: python/trunk/Modules/_collectionsmodule.c
==============================================================================
--- python/trunk/Modules/_collectionsmodule.c	(original)
+++ python/trunk/Modules/_collectionsmodule.c	Mon Sep 17 05:28:34 2007
@@ -652,7 +652,9 @@
 	if (i != 0) {
 		if (i < 0)
 			return i;
+		Py_BEGIN_ALLOW_THREADS
 		fputs("[...]", fp);
+		Py_END_ALLOW_THREADS
 		return 0;
 	}
 
@@ -660,9 +662,13 @@
 	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 @@
 	Py_DECREF(it);
 	if (PyErr_Occurred())
 		return -1;
+	Py_BEGIN_ALLOW_THREADS
 	fputs("])", fp);
+	Py_END_ALLOW_THREADS
 	return 0;
 }
 
@@ -1190,15 +1198,24 @@
 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;
 }
 

Modified: python/trunk/Objects/boolobject.c
==============================================================================
--- python/trunk/Objects/boolobject.c	(original)
+++ python/trunk/Objects/boolobject.c	Mon Sep 17 05:28:34 2007
@@ -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;
 }
 

Modified: python/trunk/Objects/complexobject.c
==============================================================================
--- python/trunk/Objects/complexobject.c	(original)
+++ python/trunk/Objects/complexobject.c	Mon Sep 17 05:28:34 2007
@@ -341,7 +341,9 @@
 	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;
 }
 

Modified: python/trunk/Objects/dictobject.c
==============================================================================
--- python/trunk/Objects/dictobject.c	(original)
+++ python/trunk/Objects/dictobject.c	Mon Sep 17 05:28:34 2007
@@ -867,11 +867,15 @@
 	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 @@
 			/* 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 @@
 			Py_DECREF(pvalue);
 		}
 	}
+	Py_BEGIN_ALLOW_THREADS
 	fprintf(fp, "}");
+	Py_END_ALLOW_THREADS
 	Py_ReprLeave((PyObject*)mp);
 	return 0;
 }

Modified: python/trunk/Objects/fileobject.c
==============================================================================
--- python/trunk/Objects/fileobject.c	(original)
+++ python/trunk/Objects/fileobject.c	Mon Sep 17 05:28:34 2007
@@ -2241,7 +2241,9 @@
 			err_closed();
 			return -1;
 		}
+		Py_BEGIN_ALLOW_THREADS
 		fputs(s, fp);
+		Py_END_ALLOW_THREADS
 		return 0;
 	}
 	else if (!PyErr_Occurred()) {

Modified: python/trunk/Objects/floatobject.c
==============================================================================
--- python/trunk/Objects/floatobject.c	(original)
+++ python/trunk/Objects/floatobject.c	Mon Sep 17 05:28:34 2007
@@ -334,7 +334,9 @@
 	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;
 }
 

Modified: python/trunk/Objects/intobject.c
==============================================================================
--- python/trunk/Objects/intobject.c	(original)
+++ python/trunk/Objects/intobject.c	Mon Sep 17 05:28:34 2007
@@ -425,7 +425,10 @@
 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;
 }
 

Modified: python/trunk/Objects/listobject.c
==============================================================================
--- python/trunk/Objects/listobject.c	(original)
+++ python/trunk/Objects/listobject.c	Mon Sep 17 05:28:34 2007
@@ -282,19 +282,28 @@
 	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;
 }

Modified: python/trunk/Objects/object.c
==============================================================================
--- python/trunk/Objects/object.c	(original)
+++ python/trunk/Objects/object.c	Mon Sep 17 05:28:34 2007
@@ -279,14 +279,18 @@
 #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)

Modified: python/trunk/Objects/setobject.c
==============================================================================
--- python/trunk/Objects/setobject.c	(original)
+++ python/trunk/Objects/setobject.c	Mon Sep 17 05:28:34 2007
@@ -577,20 +577,28 @@
 	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;
 }

Modified: python/trunk/Objects/stringobject.c
==============================================================================
--- python/trunk/Objects/stringobject.c	(original)
+++ python/trunk/Objects/stringobject.c	Mon Sep 17 05:28:34 2007
@@ -788,7 +788,7 @@
 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 @@
 	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 @@
 #else
                 fwrite(data, 1, (int)size, fp);
 #endif
+		Py_END_ALLOW_THREADS
 		return 0;
 	}
 
@@ -830,8 +832,13 @@
 	    !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 @@
 			fputc(c, fp);
 	}
 	fputc(quote, fp);
+	Py_END_ALLOW_THREADS
 	return 0;
 }
 

Modified: python/trunk/Objects/tupleobject.c
==============================================================================
--- python/trunk/Objects/tupleobject.c	(original)
+++ python/trunk/Objects/tupleobject.c	Mon Sep 17 05:28:34 2007
@@ -188,16 +188,24 @@
 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;
 }
 


More information about the Python-checkins mailing list