no longer lose data when an underlying read system call is interrupted.
IOError is no longer raised due to a read system call returning EINTR
from within these methods.
Core and Builtins
-----------------
+ - Issue #12268: File readline, readlines and read() or readall() methods
+ no longer lose data when an underlying read system call is interrupted.
+ IOError is no longer raised due to a read system call returning EINTR
+ from within these methods.
+
+- Issue #11626: Add _SizeT functions to stable ABI.
+
+- Issue #15146: Add PyType_FromSpecWithBases. Patch by Robin Schreiber.
+
- Issue #15142: Fix reference leak when deallocating instances of types
created using PyType_FromSpec().
Otherwise, the function will scan further and return garbage. */
extern Py_ssize_t _PyIO_find_line_ending(
int translated, int universal, PyObject *readnl,
- Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed);
+ int kind, char *start, char *end, Py_ssize_t *consumed);
+ /* Return 1 if an EnvironmentError with errno == EINTR is set (and then
+ clears the error indicator), 0 otherwise.
+ Should only be called when PyErr_Occurred() is true.
+ */
+ extern int _PyIO_trap_eintr(void);
#define DEFAULT_BUFFER_SIZE (8 * 1024) /* bytes */
PyObject *b;
if (has_peek) {
- _Py_IDENTIFIER(peek);
- PyObject *readahead = PyObject_CallMethod(self, "peek", "i", 1);
+ PyObject *readahead = _PyObject_CallMethodId(self, &PyId_peek, "i", 1);
-
- if (readahead == NULL)
+ if (readahead == NULL) {
+ /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
+ when EINTR occurs so we needn't do it ourselves. */
+ if (_PyIO_trap_eintr()) {
+ continue;
+ }
goto fail;
+ }
if (!PyBytes_Check(readahead)) {
PyErr_Format(PyExc_IOError,
"peek() should have returned a bytes object, "
Py_DECREF(readahead);
}
- b = PyObject_CallMethod(self, "read", "n", nreadahead);
+ b = _PyObject_CallMethodId(self, &PyId_read, "n", nreadahead);
- if (b == NULL)
+ if (b == NULL) {
+ /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
+ when EINTR occurs so we needn't do it ourselves. */
+ if (_PyIO_trap_eintr()) {
+ continue;
+ }
goto fail;
+ }
if (!PyBytes_Check(b)) {
PyErr_Format(PyExc_IOError,
"read() should have returned a bytes object, "
return NULL;
while (1) {
- PyObject *data = PyObject_CallMethod(self, "read",
- "i", DEFAULT_BUFFER_SIZE);
+ _Py_IDENTIFIER(read);
+ PyObject *data = _PyObject_CallMethodId(self, &PyId_read,
+ "i", DEFAULT_BUFFER_SIZE);
if (!data) {
+ /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
+ when EINTR occurs so we needn't do it ourselves. */
+ if (_PyIO_trap_eintr()) {
+ continue;
+ }
Py_DECREF(chunks);
return NULL;
}
/* Keep reading chunks until we have n characters to return */
while (remaining > 0) {
- res = textiowrapper_read_chunk(self);
+ res = textiowrapper_read_chunk(self, remaining);
- if (res < 0)
+ if (res < 0) {
+ /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
+ when EINTR occurs so we needn't do it ourselves. */
+ if (_PyIO_trap_eintr()) {
+ continue;
+ }
goto fail;
+ }
if (res == 0) /* EOF */
break;
if (chunks == NULL) {
/* First, get some data if necessary */
res = 1;
while (!self->decoded_chars ||
- !PyUnicode_GET_SIZE(self->decoded_chars)) {
- res = textiowrapper_read_chunk(self);
+ !PyUnicode_GET_LENGTH(self->decoded_chars)) {
+ res = textiowrapper_read_chunk(self, 0);
- if (res < 0)
+ if (res < 0) {
+ /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
+ when EINTR occurs so we needn't do it ourselves. */
+ if (_PyIO_trap_eintr()) {
+ continue;
+ }
goto error;
+ }
if (res == 0)
break;
}