Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e6c3039

Browse filesBrowse files
pythongh-135410: use a critical section around StringIO.__next__ (python#135412)
1 parent d447129 commit e6c3039
Copy full SHA for e6c3039

File tree

Expand file treeCollapse file tree

3 files changed

+32
-1
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+32
-1
lines changed
Open diff view settings
Collapse file

‎Lib/test/test_memoryio.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_memoryio.py
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55

66
import unittest
77
from test import support
8+
from test.support import threading_helper
89

910
import gc
1011
import io
1112
import _pyio as pyio
1213
import pickle
1314
import sys
1415
import weakref
16+
import threading
1517

1618
class IntLike:
1719
def __init__(self, num):
@@ -723,6 +725,22 @@ def test_newline_argument(self):
723725
for newline in (None, "", "\n", "\r", "\r\n"):
724726
self.ioclass(newline=newline)
725727

728+
@unittest.skipUnless(support.Py_GIL_DISABLED, "only meaningful under free-threading")
729+
@threading_helper.requires_working_threading()
730+
def test_concurrent_use(self):
731+
memio = self.ioclass("")
732+
733+
def use():
734+
memio.write("x" * 10)
735+
memio.readlines()
736+
737+
threads = [threading.Thread(target=use) for _ in range(8)]
738+
with threading_helper.catch_threading_exception() as cm:
739+
with threading_helper.start_threads(threads):
740+
pass
741+
742+
self.assertIsNone(cm.exc_value)
743+
726744

727745
class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin,
728746
TextIOTestMixin, unittest.TestCase):
@@ -890,6 +908,7 @@ def test_setstate(self):
890908
self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0, None))
891909

892910

911+
893912
class CStringIOPickleTest(PyStringIOPickleTest):
894913
UnsupportedOperation = io.UnsupportedOperation
895914

Collapse file
+2Lines changed: 2 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash when iterating over :class:`io.StringIO` on the :term:`free
2+
threaded <free threading>` build.
Collapse file

‎Modules/_io/stringio.c‎

Copy file name to clipboardExpand all lines: Modules/_io/stringio.c
+11-1Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ _io_StringIO_readline_impl(stringio *self, Py_ssize_t size)
404404
}
405405

406406
static PyObject *
407-
stringio_iternext(PyObject *op)
407+
stringio_iternext_lock_held(PyObject *op)
408408
{
409409
PyObject *line;
410410
stringio *self = stringio_CAST(op);
@@ -441,6 +441,16 @@ stringio_iternext(PyObject *op)
441441
return line;
442442
}
443443

444+
static PyObject *
445+
stringio_iternext(PyObject *op)
446+
{
447+
PyObject *res;
448+
Py_BEGIN_CRITICAL_SECTION(op);
449+
res = stringio_iternext_lock_held(op);
450+
Py_END_CRITICAL_SECTION();
451+
return res;
452+
}
453+
444454
/*[clinic input]
445455
@critical_section
446456
_io.StringIO.truncate

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.