gh-111965: Use critical sections to make io.BufferedIOBase and its related classes thread safe (gh-112298)

This commit is contained in:
Mayuresh Kedari 2023-11-22 16:55:07 +05:30 committed by GitHub
parent ad0e2a9332
commit fef6fb8762
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 180 additions and 40 deletions

View File

@ -8,11 +8,12 @@
*/
#include "Python.h"
#include "pycore_bytesobject.h" // _PyBytes_Join()
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pyerrors.h" // _Py_FatalErrorFormat()
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
#include "pycore_bytesobject.h" // _PyBytes_Join()
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pyerrors.h" // _Py_FatalErrorFormat()
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
#include "_iomodule.h"
@ -82,6 +83,7 @@ _bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readint
}
/*[clinic input]
@critical_section
_io._BufferedIOBase.readinto
buffer: Py_buffer(accept={rwbuffer})
/
@ -89,12 +91,13 @@ _io._BufferedIOBase.readinto
static PyObject *
_io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer)
/*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/
/*[clinic end generated code: output=8c8cda6684af8038 input=5273d20db7f56e1a]*/
{
return _bufferediobase_readinto_generic(self, buffer, 0);
}
/*[clinic input]
@critical_section
_io._BufferedIOBase.readinto1
buffer: Py_buffer(accept={rwbuffer})
/
@ -102,7 +105,7 @@ _io._BufferedIOBase.readinto1
static PyObject *
_io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer)
/*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/
/*[clinic end generated code: output=358623e4fd2b69d3 input=d6eb723dedcee654]*/
{
return _bufferediobase_readinto_generic(self, buffer, 1);
}
@ -431,12 +434,13 @@ buffered_dealloc(buffered *self)
}
/*[clinic input]
@critical_section
_io._Buffered.__sizeof__
[clinic start generated code]*/
static PyObject *
_io__Buffered___sizeof___impl(buffered *self)
/*[clinic end generated code: output=0231ef7f5053134e input=753c782d808d34df]*/
/*[clinic end generated code: output=0231ef7f5053134e input=07a32d578073ea64]*/
{
size_t res = _PyObject_SIZE(Py_TYPE(self));
if (self->buffer) {
@ -488,12 +492,13 @@ _io__Buffered__dealloc_warn(buffered *self, PyObject *source)
/* Flush and close */
/*[clinic input]
@critical_section
_io._Buffered.flush as _io__Buffered_simple_flush
[clinic start generated code]*/
static PyObject *
_io__Buffered_simple_flush_impl(buffered *self)
/*[clinic end generated code: output=29ebb3820db1bdfd input=f33ef045e7250767]*/
/*[clinic end generated code: output=29ebb3820db1bdfd input=5248cb84a65f80bd]*/
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(flush));
@ -514,12 +519,24 @@ buffered_closed(buffered *self)
}
static PyObject *
buffered_closed_get(buffered *self, void *context)
buffered_closed_get_impl(buffered *self, void *context)
{
CHECK_INITIALIZED(self)
return PyObject_GetAttr(self->raw, &_Py_ID(closed));
}
static PyObject *
buffered_closed_get(buffered *self, void *context)
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = buffered_closed_get_impl(self, context);
Py_END_CRITICAL_SECTION();
return return_value;
}
/*[clinic input]
@critical_section
_io._Buffered.close
@ -584,12 +601,13 @@ end:
}
/*[clinic input]
@critical_section
_io._Buffered.detach
[clinic start generated code]*/
static PyObject *
_io__Buffered_detach_impl(buffered *self)
/*[clinic end generated code: output=dd0fc057b8b779f7 input=482762a345cc9f44]*/
/*[clinic end generated code: output=dd0fc057b8b779f7 input=d4ef1828a678be37]*/
{
PyObject *raw;
CHECK_INITIALIZED(self)
@ -606,76 +624,105 @@ _io__Buffered_detach_impl(buffered *self)
/* Inquiries */
/*[clinic input]
@critical_section
_io._Buffered.seekable
[clinic start generated code]*/
static PyObject *
_io__Buffered_seekable_impl(buffered *self)
/*[clinic end generated code: output=90172abb5ceb6e8f input=7d35764f5fb5262b]*/
/*[clinic end generated code: output=90172abb5ceb6e8f input=e3a4fc1d297b2fd3]*/
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(seekable));
}
/*[clinic input]
@critical_section
_io._Buffered.readable
[clinic start generated code]*/
static PyObject *
_io__Buffered_readable_impl(buffered *self)
/*[clinic end generated code: output=92afa07661ecb698 input=640619addb513b8b]*/
/*[clinic end generated code: output=92afa07661ecb698 input=abe54107d59bca9a]*/
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(readable));
}
/*[clinic input]
@critical_section
_io._Buffered.writable
[clinic start generated code]*/
static PyObject *
_io__Buffered_writable_impl(buffered *self)
/*[clinic end generated code: output=4e3eee8d6f9d8552 input=b35ea396b2201554]*/
/*[clinic end generated code: output=4e3eee8d6f9d8552 input=45eb76bf6a10e6f7]*/
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(writable));
}
static PyObject *
buffered_name_get(buffered *self, void *context)
buffered_name_get_impl(buffered *self, void *context)
{
CHECK_INITIALIZED(self)
return PyObject_GetAttr(self->raw, &_Py_ID(name));
}
static PyObject *
buffered_mode_get(buffered *self, void *context)
buffered_name_get(buffered *self, void *context)
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = buffered_name_get_impl(self, context);
Py_END_CRITICAL_SECTION();
return return_value;
}
static PyObject *
buffered_mode_get_impl(buffered *self, void *context)
{
CHECK_INITIALIZED(self)
return PyObject_GetAttr(self->raw, &_Py_ID(mode));
}
static PyObject *
buffered_mode_get(buffered *self, void *context)
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = buffered_mode_get_impl(self, context);
Py_END_CRITICAL_SECTION();
return return_value;
}
/* Lower-level APIs */
/*[clinic input]
@critical_section
_io._Buffered.fileno
[clinic start generated code]*/
static PyObject *
_io__Buffered_fileno_impl(buffered *self)
/*[clinic end generated code: output=b717648d58a95ee3 input=768ea30b3f6314a7]*/
/*[clinic end generated code: output=b717648d58a95ee3 input=1c4fead777bae20a]*/
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(fileno));
}
/*[clinic input]
@critical_section
_io._Buffered.isatty
[clinic start generated code]*/
static PyObject *
_io__Buffered_isatty_impl(buffered *self)
/*[clinic end generated code: output=c20e55caae67baea input=9ea007b11559bee4]*/
/*[clinic end generated code: output=c20e55caae67baea input=e53d182d7e490e3a]*/
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(isatty));
@ -881,12 +928,13 @@ buffered_flush_and_rewind_unlocked(buffered *self)
}
/*[clinic input]
@critical_section
_io._Buffered.flush
[clinic start generated code]*/
static PyObject *
_io__Buffered_flush_impl(buffered *self)
/*[clinic end generated code: output=da2674ef1ce71f3a input=fda63444697c6bf4]*/
/*[clinic end generated code: output=da2674ef1ce71f3a input=6b30de9f083419c2]*/
{
PyObject *res;
@ -902,6 +950,7 @@ _io__Buffered_flush_impl(buffered *self)
}
/*[clinic input]
@critical_section
_io._Buffered.peek
size: Py_ssize_t = 0
/
@ -910,7 +959,7 @@ _io._Buffered.peek
static PyObject *
_io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
/*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/
/*[clinic end generated code: output=ba7a097ca230102b input=56733376f926d982]*/
{
PyObject *res = NULL;
@ -934,6 +983,7 @@ end:
}
/*[clinic input]
@critical_section
_io._Buffered.read
size as n: Py_ssize_t(accept={int, NoneType}) = -1
/
@ -941,7 +991,7 @@ _io._Buffered.read
static PyObject *
_io__Buffered_read_impl(buffered *self, Py_ssize_t n)
/*[clinic end generated code: output=f41c78bb15b9bbe9 input=7df81e82e08a68a2]*/
/*[clinic end generated code: output=f41c78bb15b9bbe9 input=bdb4b0425b295472]*/
{
PyObject *res;
@ -975,6 +1025,7 @@ _io__Buffered_read_impl(buffered *self, Py_ssize_t n)
}
/*[clinic input]
@critical_section
_io._Buffered.read1
size as n: Py_ssize_t = -1
/
@ -982,7 +1033,7 @@ _io._Buffered.read1
static PyObject *
_io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
/*[clinic end generated code: output=bcc4fb4e54d103a3 input=7d22de9630b61774]*/
/*[clinic end generated code: output=bcc4fb4e54d103a3 input=3d0ad241aa52b36c]*/
{
Py_ssize_t have, r;
PyObject *res = NULL;
@ -1111,6 +1162,7 @@ end:
}
/*[clinic input]
@critical_section
_io._Buffered.readinto
buffer: Py_buffer(accept={rwbuffer})
/
@ -1118,12 +1170,13 @@ _io._Buffered.readinto
static PyObject *
_io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
/*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/
/*[clinic end generated code: output=bcb376580b1d8170 input=777c33e7adaa2bcd]*/
{
return _buffered_readinto_generic(self, buffer, 0);
}
/*[clinic input]
@critical_section
_io._Buffered.readinto1
buffer: Py_buffer(accept={rwbuffer})
/
@ -1131,7 +1184,7 @@ _io._Buffered.readinto1
static PyObject *
_io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
/*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/
/*[clinic end generated code: output=6e5c6ac5868205d6 input=ef03cc5fc92a6895]*/
{
return _buffered_readinto_generic(self, buffer, 1);
}
@ -1246,6 +1299,7 @@ end_unlocked:
}
/*[clinic input]
@critical_section
_io._Buffered.readline
size: Py_ssize_t(accept={int, NoneType}) = -1
/
@ -1253,7 +1307,7 @@ _io._Buffered.readline
static PyObject *
_io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
/*[clinic end generated code: output=24dd2aa6e33be83c input=673b6240e315ef8a]*/
/*[clinic end generated code: output=24dd2aa6e33be83c input=e81ca5abd4280776]*/
{
CHECK_INITIALIZED(self)
return _buffered_readline(self, size);
@ -1261,12 +1315,13 @@ _io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
/*[clinic input]
@critical_section
_io._Buffered.tell
[clinic start generated code]*/
static PyObject *
_io__Buffered_tell_impl(buffered *self)
/*[clinic end generated code: output=386972ae84716c1e input=ad61e04a6b349573]*/
/*[clinic end generated code: output=386972ae84716c1e input=ab12e67d8abcb42f]*/
{
Py_off_t pos;
@ -1280,6 +1335,7 @@ _io__Buffered_tell_impl(buffered *self)
}
/*[clinic input]
@critical_section
_io._Buffered.seek
target as targetobj: object
whence: int = 0
@ -1288,7 +1344,7 @@ _io._Buffered.seek
static PyObject *
_io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
/*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/
/*[clinic end generated code: output=7ae0e8dc46efdefb input=b5a12be70e0ad07b]*/
{
Py_off_t target, n;
PyObject *res = NULL;
@ -1377,6 +1433,7 @@ end:
}
/*[clinic input]
@critical_section
_io._Buffered.truncate
cls: defining_class
pos: object = None
@ -1385,7 +1442,7 @@ _io._Buffered.truncate
static PyObject *
_io__Buffered_truncate_impl(buffered *self, PyTypeObject *cls, PyObject *pos)
/*[clinic end generated code: output=fe3882fbffe79f1a input=f5b737d97d76303f]*/
/*[clinic end generated code: output=fe3882fbffe79f1a input=e3cbf794575bd794]*/
{
PyObject *res = NULL;
@ -1999,6 +2056,7 @@ error:
}
/*[clinic input]
@critical_section
_io.BufferedWriter.write
buffer: Py_buffer
/
@ -2006,7 +2064,7 @@ _io.BufferedWriter.write
static PyObject *
_io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
/*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/
/*[clinic end generated code: output=7f8d1365759bfc6b input=6a9c041de0c337be]*/
{
PyObject *res = NULL;
Py_ssize_t written, avail, remaining;

View File

@ -31,7 +31,9 @@ _io__BufferedIOBase_readinto(PyObject *self, PyObject *arg)
_PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg);
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__BufferedIOBase_readinto_impl(self, &buffer);
Py_END_CRITICAL_SECTION();
exit:
/* Cleanup for buffer */
@ -63,7 +65,9 @@ _io__BufferedIOBase_readinto1(PyObject *self, PyObject *arg)
_PyArg_BadArgument("readinto1", "argument", "read-write bytes-like object", arg);
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__BufferedIOBase_readinto1_impl(self, &buffer);
Py_END_CRITICAL_SECTION();
exit:
/* Cleanup for buffer */
@ -283,7 +287,13 @@ _io__Buffered___sizeof___impl(buffered *self);
static PyObject *
_io__Buffered___sizeof__(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered___sizeof___impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered___sizeof___impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered__dealloc_warn__doc__,
@ -308,7 +318,13 @@ _io__Buffered_simple_flush_impl(buffered *self);
static PyObject *
_io__Buffered_simple_flush(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_simple_flush_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_simple_flush_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_close__doc__,
@ -348,7 +364,13 @@ _io__Buffered_detach_impl(buffered *self);
static PyObject *
_io__Buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_detach_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_detach_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_seekable__doc__,
@ -365,7 +387,13 @@ _io__Buffered_seekable_impl(buffered *self);
static PyObject *
_io__Buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_seekable_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_seekable_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_readable__doc__,
@ -382,7 +410,13 @@ _io__Buffered_readable_impl(buffered *self);
static PyObject *
_io__Buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_readable_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_readable_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_writable__doc__,
@ -399,7 +433,13 @@ _io__Buffered_writable_impl(buffered *self);
static PyObject *
_io__Buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_writable_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_writable_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_fileno__doc__,
@ -416,7 +456,13 @@ _io__Buffered_fileno_impl(buffered *self);
static PyObject *
_io__Buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_fileno_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_fileno_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_isatty__doc__,
@ -433,7 +479,13 @@ _io__Buffered_isatty_impl(buffered *self);
static PyObject *
_io__Buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_isatty_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_isatty_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_flush__doc__,
@ -450,7 +502,13 @@ _io__Buffered_flush_impl(buffered *self);
static PyObject *
_io__Buffered_flush(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_flush_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_flush_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_peek__doc__,
@ -489,7 +547,9 @@ _io__Buffered_peek(buffered *self, PyObject *const *args, Py_ssize_t nargs)
size = ival;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_peek_impl(self, size);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -522,7 +582,9 @@ _io__Buffered_read(buffered *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_read_impl(self, n);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -564,7 +626,9 @@ _io__Buffered_read1(buffered *self, PyObject *const *args, Py_ssize_t nargs)
n = ival;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_read1_impl(self, n);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -591,7 +655,9 @@ _io__Buffered_readinto(buffered *self, PyObject *arg)
_PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg);
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_readinto_impl(self, &buffer);
Py_END_CRITICAL_SECTION();
exit:
/* Cleanup for buffer */
@ -623,7 +689,9 @@ _io__Buffered_readinto1(buffered *self, PyObject *arg)
_PyArg_BadArgument("readinto1", "argument", "read-write bytes-like object", arg);
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_readinto1_impl(self, &buffer);
Py_END_CRITICAL_SECTION();
exit:
/* Cleanup for buffer */
@ -661,7 +729,9 @@ _io__Buffered_readline(buffered *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_readline_impl(self, size);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -681,7 +751,13 @@ _io__Buffered_tell_impl(buffered *self);
static PyObject *
_io__Buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored))
{
return _io__Buffered_tell_impl(self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_tell_impl(self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(_io__Buffered_seek__doc__,
@ -714,7 +790,9 @@ _io__Buffered_seek(buffered *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_seek_impl(self, targetobj, whence);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -760,7 +838,9 @@ _io__Buffered_truncate(buffered *self, PyTypeObject *cls, PyObject *const *args,
}
pos = args[0];
skip_optional_posonly:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_truncate_impl(self, cls, pos);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -936,7 +1016,9 @@ _io_BufferedWriter_write(buffered *self, PyObject *arg)
if (PyObject_GetBuffer(arg, &buffer, PyBUF_SIMPLE) != 0) {
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io_BufferedWriter_write_impl(self, &buffer);
Py_END_CRITICAL_SECTION();
exit:
/* Cleanup for buffer */
@ -1082,4 +1164,4 @@ skip_optional_pos:
exit:
return return_value;
}
/*[clinic end generated code: output=2d5f735188df3163 input=a9049054013a1b77]*/
/*[clinic end generated code: output=e8ad39a45531d7f2 input=a9049054013a1b77]*/