From 974d87937cbe38d6f1f04b324faa472712fa1d0a Mon Sep 17 00:00:00 2001 From: Ivy Xu Date: Sun, 26 Jul 2026 00:49:25 +0800 Subject: [PATCH 1/3] Replace `PyThread_type_lock` with `PyMutex` in `bufferedio.c` --- Modules/_io/bufferedio.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 5537947f6a51c11..ef745a2de1681e5 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -254,7 +254,7 @@ typedef struct { isn't ready for writing. */ Py_off_t write_end; - PyThread_type_lock lock; + PyMutex mutex; volatile unsigned long owner; Py_ssize_t buffer_size; @@ -304,8 +304,9 @@ _enter_buffered_busy(buffered *self) PyInterpreterState *interp = _PyInterpreterState_GET(); relax_locking = _Py_IsInterpreterFinalizing(interp); Py_BEGIN_ALLOW_THREADS - if (!relax_locking) - st = PyThread_acquire_lock(self->lock, 1); + if (!relax_locking) { + PyMutex_Lock(&self->mutex); + } else { /* When finalizing, we don't want a deadlock to happen with daemon * threads abruptly shut down while they owned the lock. @@ -313,7 +314,7 @@ _enter_buffered_busy(buffered *self) * Note that non-daemon threads have already exited here, so this * shouldn't affect carefully written threaded I/O code. */ - st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0); + st = _PyMutex_LockTimed(&self->mutex, (PyTime_t)1e6, 0); } Py_END_ALLOW_THREADS if (relax_locking && st != PY_LOCK_ACQUIRED) { @@ -327,14 +328,14 @@ _enter_buffered_busy(buffered *self) } #define ENTER_BUFFERED(self) \ - ( (PyThread_acquire_lock(self->lock, 0) ? \ + ( (_PyMutex_LockTimed(&self->mutex, (PyTime_t)0, 0) ? \ 1 : _enter_buffered_busy(self)) \ && (self->owner = PyThread_get_thread_ident(), 1) ) #define LEAVE_BUFFERED(self) \ do { \ self->owner = 0; \ - PyThread_release_lock(self->lock); \ + PyMutex_Unlock(&self->mutex); \ } while(0); #define CHECK_INITIALIZED(self) \ @@ -436,10 +437,6 @@ buffered_dealloc(PyObject *op) PyMem_Free(self->buffer); self->buffer = NULL; } - if (self->lock) { - PyThread_free_lock(self->lock); - self->lock = NULL; - } (void)buffered_clear(op); tp->tp_free(self); Py_DECREF(tp); @@ -850,13 +847,7 @@ _buffered_init(buffered *self) PyErr_NoMemory(); return -1; } - if (self->lock) - PyThread_free_lock(self->lock); - self->lock = PyThread_allocate_lock(); - if (self->lock == NULL) { - PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock"); - return -1; - } + self->mutex = (PyMutex){0}; self->owner = 0; /* Find out whether buffer_size is a power of 2 */ /* XXX is this optimization useful? */ From 2b75a5b380035ecb9f0a26f5d5e5997c2fe1bb9f Mon Sep 17 00:00:00 2001 From: Ivy Xu Date: Sun, 26 Jul 2026 14:02:22 +0800 Subject: [PATCH 2/3] Fix the timeout value --- Modules/_io/bufferedio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index ef745a2de1681e5..4500691dc2804b0 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -314,7 +314,7 @@ _enter_buffered_busy(buffered *self) * Note that non-daemon threads have already exited here, so this * shouldn't affect carefully written threaded I/O code. */ - st = _PyMutex_LockTimed(&self->mutex, (PyTime_t)1e6, 0); + st = _PyMutex_LockTimed(&self->mutex, (PyTime_t)1e9, 0); } Py_END_ALLOW_THREADS if (relax_locking && st != PY_LOCK_ACQUIRED) { From b1a627e9de6f1d7e69d5ce968b06e54e5a531674 Mon Sep 17 00:00:00 2001 From: Ivy Xu Date: Sun, 26 Jul 2026 14:51:52 +0800 Subject: [PATCH 3/3] Fix uninitialized warning --- Modules/_io/bufferedio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 4500691dc2804b0..7421dab91b2cf2a 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -306,6 +306,7 @@ _enter_buffered_busy(buffered *self) Py_BEGIN_ALLOW_THREADS if (!relax_locking) { PyMutex_Lock(&self->mutex); + st = PY_LOCK_ACQUIRED; } else { /* When finalizing, we don't want a deadlock to happen with daemon