@@ -1719,16 +1719,26 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
17191719 bytes_len = PyBytes_GET_SIZE (b );
17201720 }
17211721
1722- if (self -> pending_bytes == NULL ) {
1723- self -> pending_bytes_count = 0 ;
1724- self -> pending_bytes = b ;
1725- }
1726- else if (self -> pending_bytes_count + bytes_len > self -> chunk_size ) {
1727- // Prevent to concatenate more than chunk_size data.
1728- if (_textiowrapper_writeflush (self ) < 0 ) {
1729- Py_DECREF (b );
1730- return NULL ;
1722+ // We should avoid concatinating huge data.
1723+ // Flush the buffer before adding b to the buffer if b is not small.
1724+ // https://github.com/python/cpython/issues/87426
1725+ if (bytes_len >= self -> chunk_size ) {
1726+ // _textiowrapper_writeflush() calls buffer.write().
1727+ // self->pending_bytes can be appended during buffer->write()
1728+ // or other thread.
1729+ // We need to loop until buffer becomes empty.
1730+ // https://github.com/python/cpython/issues/118138
1731+ // https://github.com/python/cpython/issues/119506
1732+ while (self -> pending_bytes != NULL ) {
1733+ if (_textiowrapper_writeflush (self ) < 0 ) {
1734+ Py_DECREF (b );
1735+ return NULL ;
1736+ }
17311737 }
1738+ }
1739+
1740+ if (self -> pending_bytes == NULL ) {
1741+ assert (self -> pending_bytes_count == 0 );
17321742 self -> pending_bytes = b ;
17331743 }
17341744 else if (!PyList_CheckExact (self -> pending_bytes )) {
@@ -1737,6 +1747,9 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
17371747 Py_DECREF (b );
17381748 return NULL ;
17391749 }
1750+ // Since Python 3.12, allocating GC object won't trigger GC and release
1751+ // GIL. See https://github.com/python/cpython/issues/97922
1752+ assert (!PyList_CheckExact (self -> pending_bytes ));
17401753 PyList_SET_ITEM (list , 0 , self -> pending_bytes );
17411754 PyList_SET_ITEM (list , 1 , b );
17421755 self -> pending_bytes = list ;
0 commit comments