Add a bunch of GIL release/acquire points in tp_print implementations and for

PyObject_Print().

Closes issue #1164.
This commit is contained in:
Brett Cannon 2007-09-17 03:28:34 +00:00
parent d36a60e1e3
commit 0153159e67
13 changed files with 89 additions and 8 deletions

View File

@ -12,6 +12,11 @@ What's New in Python 2.6 alpha 1?
Core and builtins 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 - Issue #1147: Exceptions were directly allowing string exceptions in their
throw() method even though string exceptions no longer allowed. throw() method even though string exceptions no longer allowed.

View File

@ -652,7 +652,9 @@ deque_tp_print(PyObject *deque, FILE *fp, int flags)
if (i != 0) { if (i != 0) {
if (i < 0) if (i < 0)
return i; return i;
Py_BEGIN_ALLOW_THREADS
fputs("[...]", fp); fputs("[...]", fp);
Py_END_ALLOW_THREADS
return 0; return 0;
} }
@ -660,9 +662,13 @@ deque_tp_print(PyObject *deque, FILE *fp, int flags)
if (it == NULL) if (it == NULL)
return -1; return -1;
Py_BEGIN_ALLOW_THREADS
fputs("deque([", fp); fputs("deque([", fp);
Py_END_ALLOW_THREADS
while ((item = PyIter_Next(it)) != NULL) { while ((item = PyIter_Next(it)) != NULL) {
Py_BEGIN_ALLOW_THREADS
fputs(emit, fp); fputs(emit, fp);
Py_END_ALLOW_THREADS
emit = separator; emit = separator;
if (PyObject_Print(item, fp, 0) != 0) { if (PyObject_Print(item, fp, 0) != 0) {
Py_DECREF(item); Py_DECREF(item);
@ -676,7 +682,9 @@ deque_tp_print(PyObject *deque, FILE *fp, int flags)
Py_DECREF(it); Py_DECREF(it);
if (PyErr_Occurred()) if (PyErr_Occurred())
return -1; return -1;
Py_BEGIN_ALLOW_THREADS
fputs("])", fp); fputs("])", fp);
Py_END_ALLOW_THREADS
return 0; return 0;
} }
@ -1190,15 +1198,24 @@ static int
defdict_print(defdictobject *dd, FILE *fp, int flags) defdict_print(defdictobject *dd, FILE *fp, int flags)
{ {
int sts; int sts;
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "defaultdict("); fprintf(fp, "defaultdict(");
if (dd->default_factory == NULL) Py_END_ALLOW_THREADS
if (dd->default_factory == NULL) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "None"); fprintf(fp, "None");
Py_END_ALLOW_THREADS
}
else { else {
PyObject_Print(dd->default_factory, fp, 0); PyObject_Print(dd->default_factory, fp, 0);
} }
Py_BEGIN_ALLOW_THREADS
fprintf(fp, ", "); fprintf(fp, ", ");
Py_END_ALLOW_THREADS
sts = PyDict_Type.tp_print((PyObject *)dd, fp, 0); sts = PyDict_Type.tp_print((PyObject *)dd, fp, 0);
Py_BEGIN_ALLOW_THREADS
fprintf(fp, ")"); fprintf(fp, ")");
Py_END_ALLOW_THREADS
return sts; return sts;
} }

View File

@ -7,7 +7,9 @@
static int static int
bool_print(PyBoolObject *self, FILE *fp, int flags) bool_print(PyBoolObject *self, FILE *fp, int flags)
{ {
Py_BEGIN_ALLOW_THREADS
fputs(self->ob_ival == 0 ? "False" : "True", fp); fputs(self->ob_ival == 0 ? "False" : "True", fp);
Py_END_ALLOW_THREADS
return 0; return 0;
} }

View File

@ -341,7 +341,9 @@ complex_print(PyComplexObject *v, FILE *fp, int flags)
char buf[100]; char buf[100];
complex_to_buf(buf, sizeof(buf), v, complex_to_buf(buf, sizeof(buf), v,
(flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR); (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
Py_BEGIN_ALLOW_THREADS
fputs(buf, fp); fputs(buf, fp);
Py_END_ALLOW_THREADS
return 0; return 0;
} }

View File

@ -867,11 +867,15 @@ dict_print(register dictobject *mp, register FILE *fp, register int flags)
if (status != 0) { if (status != 0) {
if (status < 0) if (status < 0)
return status; return status;
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "{...}"); fprintf(fp, "{...}");
Py_END_ALLOW_THREADS
return 0; return 0;
} }
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "{"); fprintf(fp, "{");
Py_END_ALLOW_THREADS
any = 0; any = 0;
for (i = 0; i <= mp->ma_mask; i++) { for (i = 0; i <= mp->ma_mask; i++) {
dictentry *ep = mp->ma_table + 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 /* Prevent PyObject_Repr from deleting value during
key format */ key format */
Py_INCREF(pvalue); Py_INCREF(pvalue);
if (any++ > 0) if (any++ > 0) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, ", "); fprintf(fp, ", ");
Py_END_ALLOW_THREADS
}
if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) { if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) {
Py_DECREF(pvalue); Py_DECREF(pvalue);
Py_ReprLeave((PyObject*)mp); Py_ReprLeave((PyObject*)mp);
return -1; return -1;
} }
Py_BEGIN_ALLOW_THREADS
fprintf(fp, ": "); fprintf(fp, ": ");
Py_END_ALLOW_THREADS
if (PyObject_Print(pvalue, fp, 0) != 0) { if (PyObject_Print(pvalue, fp, 0) != 0) {
Py_DECREF(pvalue); Py_DECREF(pvalue);
Py_ReprLeave((PyObject*)mp); Py_ReprLeave((PyObject*)mp);
@ -896,7 +905,9 @@ dict_print(register dictobject *mp, register FILE *fp, register int flags)
Py_DECREF(pvalue); Py_DECREF(pvalue);
} }
} }
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "}"); fprintf(fp, "}");
Py_END_ALLOW_THREADS
Py_ReprLeave((PyObject*)mp); Py_ReprLeave((PyObject*)mp);
return 0; return 0;
} }

View File

@ -2241,7 +2241,9 @@ PyFile_WriteString(const char *s, PyObject *f)
err_closed(); err_closed();
return -1; return -1;
} }
Py_BEGIN_ALLOW_THREADS
fputs(s, fp); fputs(s, fp);
Py_END_ALLOW_THREADS
return 0; return 0;
} }
else if (!PyErr_Occurred()) { else if (!PyErr_Occurred()) {

View File

@ -334,7 +334,9 @@ float_print(PyFloatObject *v, FILE *fp, int flags)
char buf[100]; char buf[100];
format_float(buf, sizeof(buf), v, format_float(buf, sizeof(buf), v,
(flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR); (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
Py_BEGIN_ALLOW_THREADS
fputs(buf, fp); fputs(buf, fp);
Py_END_ALLOW_THREADS
return 0; return 0;
} }

View File

@ -425,7 +425,10 @@ static int
int_print(PyIntObject *v, FILE *fp, int flags) int_print(PyIntObject *v, FILE *fp, int flags)
/* flags -- not used but required by interface */ /* 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; return 0;
} }

View File

@ -282,19 +282,28 @@ list_print(PyListObject *op, FILE *fp, int flags)
if (rc != 0) { if (rc != 0) {
if (rc < 0) if (rc < 0)
return rc; return rc;
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "[...]"); fprintf(fp, "[...]");
Py_END_ALLOW_THREADS
return 0; return 0;
} }
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "["); fprintf(fp, "[");
Py_END_ALLOW_THREADS
for (i = 0; i < Py_Size(op); i++) { for (i = 0; i < Py_Size(op); i++) {
if (i > 0) if (i > 0) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, ", "); fprintf(fp, ", ");
Py_END_ALLOW_THREADS
}
if (PyObject_Print(op->ob_item[i], fp, 0) != 0) { if (PyObject_Print(op->ob_item[i], fp, 0) != 0) {
Py_ReprLeave((PyObject *)op); Py_ReprLeave((PyObject *)op);
return -1; return -1;
} }
} }
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "]"); fprintf(fp, "]");
Py_END_ALLOW_THREADS
Py_ReprLeave((PyObject *)op); Py_ReprLeave((PyObject *)op);
return 0; return 0;
} }

View File

@ -279,14 +279,18 @@ internal_print(PyObject *op, FILE *fp, int flags, int nesting)
#endif #endif
clearerr(fp); /* Clear any previous error condition */ clearerr(fp); /* Clear any previous error condition */
if (op == NULL) { if (op == NULL) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "<nil>"); fprintf(fp, "<nil>");
Py_END_ALLOW_THREADS
} }
else { else {
if (op->ob_refcnt <= 0) if (op->ob_refcnt <= 0)
/* XXX(twouters) cast refcount to long until %zd is /* XXX(twouters) cast refcount to long until %zd is
universally available */ universally available */
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "<refcnt %ld at %p>", fprintf(fp, "<refcnt %ld at %p>",
(long)op->ob_refcnt, op); (long)op->ob_refcnt, op);
Py_END_ALLOW_THREADS
else if (Py_Type(op)->tp_print == NULL) { else if (Py_Type(op)->tp_print == NULL) {
PyObject *s; PyObject *s;
if (flags & Py_PRINT_RAW) if (flags & Py_PRINT_RAW)

View File

@ -577,20 +577,28 @@ set_tp_print(PySetObject *so, FILE *fp, int flags)
if (status != 0) { if (status != 0) {
if (status < 0) if (status < 0)
return status; return status;
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "%s(...)", so->ob_type->tp_name); fprintf(fp, "%s(...)", so->ob_type->tp_name);
Py_END_ALLOW_THREADS
return 0; return 0;
} }
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "%s([", so->ob_type->tp_name); fprintf(fp, "%s([", so->ob_type->tp_name);
Py_END_ALLOW_THREADS
while (set_next(so, &pos, &entry)) { while (set_next(so, &pos, &entry)) {
Py_BEGIN_ALLOW_THREADS
fputs(emit, fp); fputs(emit, fp);
Py_END_ALLOW_THREADS
emit = separator; emit = separator;
if (PyObject_Print(entry->key, fp, 0) != 0) { if (PyObject_Print(entry->key, fp, 0) != 0) {
Py_ReprLeave((PyObject*)so); Py_ReprLeave((PyObject*)so);
return -1; return -1;
} }
} }
Py_BEGIN_ALLOW_THREADS
fputs("])", fp); fputs("])", fp);
Py_END_ALLOW_THREADS
Py_ReprLeave((PyObject*)so); Py_ReprLeave((PyObject*)so);
return 0; return 0;
} }

View File

@ -788,7 +788,7 @@ PyString_AsStringAndSize(register PyObject *obj,
static int static int
string_print(PyStringObject *op, FILE *fp, int flags) string_print(PyStringObject *op, FILE *fp, int flags)
{ {
Py_ssize_t i; Py_ssize_t i, str_len;
char c; char c;
int quote; int quote;
@ -806,6 +806,7 @@ string_print(PyStringObject *op, FILE *fp, int flags)
if (flags & Py_PRINT_RAW) { if (flags & Py_PRINT_RAW) {
char *data = op->ob_sval; char *data = op->ob_sval;
Py_ssize_t size = Py_Size(op); Py_ssize_t size = Py_Size(op);
Py_BEGIN_ALLOW_THREADS
while (size > INT_MAX) { while (size > INT_MAX) {
/* Very long strings cannot be written atomically. /* Very long strings cannot be written atomically.
* But don't write exactly INT_MAX bytes at a time * But don't write exactly INT_MAX bytes at a time
@ -821,6 +822,7 @@ string_print(PyStringObject *op, FILE *fp, int flags)
#else #else
fwrite(data, 1, (int)size, fp); fwrite(data, 1, (int)size, fp);
#endif #endif
Py_END_ALLOW_THREADS
return 0; return 0;
} }
@ -830,8 +832,13 @@ string_print(PyStringObject *op, FILE *fp, int flags)
!memchr(op->ob_sval, '"', Py_Size(op))) !memchr(op->ob_sval, '"', Py_Size(op)))
quote = '"'; quote = '"';
str_len = Py_Size(op);
Py_BEGIN_ALLOW_THREADS
fputc(quote, fp); 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]; c = op->ob_sval[i];
if (c == quote || c == '\\') if (c == quote || c == '\\')
fprintf(fp, "\\%c", c); fprintf(fp, "\\%c", c);
@ -847,6 +854,7 @@ string_print(PyStringObject *op, FILE *fp, int flags)
fputc(c, fp); fputc(c, fp);
} }
fputc(quote, fp); fputc(quote, fp);
Py_END_ALLOW_THREADS
return 0; return 0;
} }

View File

@ -188,16 +188,24 @@ static int
tupleprint(PyTupleObject *op, FILE *fp, int flags) tupleprint(PyTupleObject *op, FILE *fp, int flags)
{ {
Py_ssize_t i; Py_ssize_t i;
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "("); fprintf(fp, "(");
Py_END_ALLOW_THREADS
for (i = 0; i < Py_Size(op); i++) { for (i = 0; i < Py_Size(op); i++) {
if (i > 0) if (i > 0) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, ", "); fprintf(fp, ", ");
Py_END_ALLOW_THREADS
}
if (PyObject_Print(op->ob_item[i], fp, 0) != 0) if (PyObject_Print(op->ob_item[i], fp, 0) != 0)
return -1; return -1;
} }
if (Py_Size(op) == 1) i = Py_Size(op);
Py_BEGIN_ALLOW_THREADS
if (i == 1)
fprintf(fp, ","); fprintf(fp, ",");
fprintf(fp, ")"); fprintf(fp, ")");
Py_END_ALLOW_THREADS
return 0; return 0;
} }