diff options
Diffstat (limited to 'Modules/_io/bufferedio.c')
-rw-r--r-- | Modules/_io/bufferedio.c | 94 |
1 files changed, 59 insertions, 35 deletions
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index e2d6025d33f..bb77acc0705 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -69,7 +69,7 @@ bufferediobase_readinto(PyObject *self, PyObject *args) static PyObject * bufferediobase_unsupported(const char *message) { - PyErr_SetString(_PyIO_unsupported_operation, message); + PyErr_SetString(IO_STATE->unsupported_operation, message); return NULL; } @@ -197,6 +197,7 @@ typedef struct { int detached; int readable; int writable; + int deallocating; /* True if this is a vanilla Buffered object (rather than a user derived class) *and* the raw stream is a vanilla FileIO object. */ @@ -265,13 +266,8 @@ static int _enter_buffered_busy(buffered *self) { if (self->owner == PyThread_get_thread_ident()) { - PyObject *r = PyObject_Repr((PyObject *) self); - if (r != NULL) { - PyErr_Format(PyExc_RuntimeError, - "reentrant call inside %s", - PyString_AS_STRING(r)); - Py_DECREF(r); - } + PyErr_Format(PyExc_RuntimeError, + "reentrant call inside %R", self); return 0; } Py_BEGIN_ALLOW_THREADS @@ -365,6 +361,7 @@ _enter_buffered_busy(buffered *self) static void buffered_dealloc(buffered *self) { + self->deallocating = 1; if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0) return; _PyObject_GC_UNTRACK(self); @@ -416,6 +413,23 @@ buffered_clear(buffered *self) return 0; } +/* Because this can call arbitrary code, it shouldn't be called when + the refcount is 0 (that is, not directly from tp_dealloc unless + the refcount has been temporarily re-incremented). */ +static PyObject * +buffered_dealloc_warn(buffered *self, PyObject *source) +{ + if (self->ok && self->raw) { + PyObject *r; + r = PyObject_CallMethod(self->raw, "_dealloc_warn", "O", source); + if (r) + Py_DECREF(r); + else + PyErr_Clear(); + } + Py_RETURN_NONE; +} + /* * _BufferedIOMixin methods * This is not a class, just a collection of methods that will be reused @@ -455,7 +469,7 @@ buffered_closed_get(buffered *self, void *context) static PyObject * buffered_close(buffered *self, PyObject *args) { - PyObject *res = NULL, *exc = NULL, *val, *tb; + PyObject *res = NULL; int r; CHECK_INITIALIZED(self) @@ -470,30 +484,26 @@ buffered_close(buffered *self, PyObject *args) Py_INCREF(res); goto end; } + + if (self->deallocating) { + PyObject *r = buffered_dealloc_warn(self, (PyObject *) self); + if (r) + Py_DECREF(r); + else + PyErr_Clear(); + } /* flush() will most probably re-take the lock, so drop it first */ LEAVE_BUFFERED(self) res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); if (!ENTER_BUFFERED(self)) return NULL; - if (res == NULL) - PyErr_Fetch(&exc, &val, &tb); - else - Py_DECREF(res); + if (res == NULL) { + goto end; + } + Py_XDECREF(res); res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL); - if (exc != NULL) { - if (res != NULL) { - Py_CLEAR(res); - PyErr_Restore(exc, val, tb); - } - else { - Py_DECREF(exc); - Py_XDECREF(val); - Py_XDECREF(tb); - } - } - end: LEAVE_BUFFERED(self) return res; @@ -570,6 +580,15 @@ buffered_isatty(buffered *self, PyObject *args) return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL); } +/* Serialization */ + +static PyObject * +buffered_getstate(buffered *self, PyObject *args) +{ + PyErr_Format(PyExc_TypeError, + "cannot serialize '%s' object", Py_TYPE(self)->tp_name); + return NULL; +} /* Forward decls */ static PyObject * @@ -1090,6 +1109,9 @@ buffered_seek(buffered *self, PyObject *args) CHECK_CLOSED(self, "seek of closed file") + if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL) + return NULL; + target = PyNumber_AsOff_t(targetobj, PyExc_ValueError); if (target == -1 && PyErr_Occurred()) return NULL; @@ -1226,17 +1248,12 @@ buffered_repr(buffered *self) PyErr_Clear(); else return NULL; - res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name); + res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name); } else { - PyObject *repr = PyObject_Repr(nameobj); + res = PyUnicode_FromFormat("<%s name=%R>", + Py_TYPE(self)->tp_name, nameobj); Py_DECREF(nameobj); - if (repr == NULL) - return NULL; - res = PyString_FromFormat("<%s name=%s>", - Py_TYPE(self)->tp_name, - PyString_AS_STRING(repr)); - Py_DECREF(repr); } return res; } @@ -1575,6 +1592,8 @@ static PyMethodDef bufferedreader_methods[] = { {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, + {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, + {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, {"read", (PyCFunction)buffered_read, METH_VARARGS}, {"peek", (PyCFunction)buffered_peek, METH_VARARGS}, @@ -1820,7 +1839,7 @@ bufferedwriter_write(buffered *self, PyObject *args) Py_off_t offset; CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "s*:write", &buf)) { + if (!PyArg_ParseTuple(args, "y*:write", &buf)) { return NULL; } @@ -1970,6 +1989,8 @@ static PyMethodDef bufferedwriter_methods[] = { {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, + {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, + {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS}, {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, @@ -2241,6 +2262,8 @@ static PyMethodDef bufferedrwpair_methods[] = { {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS}, {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS}, + {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, + {NULL, NULL} }; @@ -2360,6 +2383,8 @@ static PyMethodDef bufferedrandom_methods[] = { {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, + {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, + {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, @@ -2430,4 +2455,3 @@ PyTypeObject PyBufferedRandom_Type = { 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ }; - |