diff options
author | nechda <nechda@yandex-team.com> | 2024-08-04 13:43:56 +0300 |
---|---|---|
committer | nechda <nechda@yandex-team.com> | 2024-08-04 13:53:51 +0300 |
commit | e30f7061bad712a7934e383fef27613fc6a1b2d7 (patch) | |
tree | fed6a6490d45ffd04aca8a0d6a36e6c198ddb53e | |
parent | 55c4d6e43a8d293d088b2501098a802a40cade9a (diff) | |
download | ydb-e30f7061bad712a7934e383fef27613fc6a1b2d7.tar.gz |
fix _io.TextIOWrapper.write() write during flush
816f3097d548522bcfae2b763098747304285d0f
-rw-r--r-- | contrib/tools/python3/Modules/_io/textio.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/contrib/tools/python3/Modules/_io/textio.c b/contrib/tools/python3/Modules/_io/textio.c index 14dd19d95c..4a1ba22d38 100644 --- a/contrib/tools/python3/Modules/_io/textio.c +++ b/contrib/tools/python3/Modules/_io/textio.c @@ -1723,16 +1723,26 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) bytes_len = PyBytes_GET_SIZE(b); } - if (self->pending_bytes == NULL) { - self->pending_bytes_count = 0; - self->pending_bytes = b; - } - else if (self->pending_bytes_count + bytes_len > self->chunk_size) { - // Prevent to concatenate more than chunk_size data. - if (_textiowrapper_writeflush(self) < 0) { - Py_DECREF(b); - return NULL; + // We should avoid concatinating huge data. + // Flush the buffer before adding b to the buffer if b is not small. + // https://github.com/python/cpython/issues/87426 + if (bytes_len >= self->chunk_size) { + // _textiowrapper_writeflush() calls buffer.write(). + // self->pending_bytes can be appended during buffer->write() + // or other thread. + // We need to loop until buffer becomes empty. + // https://github.com/python/cpython/issues/118138 + // https://github.com/python/cpython/issues/119506 + while (self->pending_bytes != NULL) { + if (_textiowrapper_writeflush(self) < 0) { + Py_DECREF(b); + return NULL; + } } + } + + if (self->pending_bytes == NULL) { + assert(self->pending_bytes_count == 0); self->pending_bytes = b; } else if (!PyList_CheckExact(self->pending_bytes)) { @@ -1741,6 +1751,9 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) Py_DECREF(b); return NULL; } + // Since Python 3.12, allocating GC object won't trigger GC and release + // GIL. See https://github.com/python/cpython/issues/97922 + assert(!PyList_CheckExact(self->pending_bytes)); PyList_SET_ITEM(list, 0, self->pending_bytes); PyList_SET_ITEM(list, 1, b); self->pending_bytes = list; |