aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Modules/_io/bufferedio.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_io/bufferedio.c')
-rw-r--r--Modules/_io/bufferedio.c94
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 */
};
-