summaryrefslogtreecommitdiff
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-04-07 23:11:49 +0200
committerGitHub <noreply@github.com>2020-04-07 23:11:49 +0200
commit87255be6964979b5abdc4b9dcf81cdcfdad6e753 (patch)
tree30f3c5a680dd7ed6435841ecd38166de7654503e /Python
parent48b069a003ba6c684a9ba78493fbbec5e89f10b8 (diff)
downloadcpython-git-87255be6964979b5abdc4b9dcf81cdcfdad6e753.tar.gz
bpo-40089: Add _at_fork_reinit() method to locks (GH-19195)
Add a private _at_fork_reinit() method to _thread.Lock, _thread.RLock, threading.RLock and threading.Condition classes: reinitialize the lock after fork in the child process; reset the lock to the unlocked state. Rename also the private _reset_internal_locks() method of threading.Event to _at_fork_reinit(). * Add _PyThread_at_fork_reinit() private function. It is excluded from the limited C API. * threading.Thread._reset_internal_locks() now calls _at_fork_reinit() on self._tstate_lock rather than creating a new Python lock object.
Diffstat (limited to 'Python')
-rw-r--r--Python/thread_pthread.h20
1 files changed, 20 insertions, 0 deletions
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 40e2e117a2..e3497e7d59 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -694,6 +694,26 @@ PyThread_release_lock(PyThread_type_lock lock)
#endif /* USE_SEMAPHORES */
int
+_PyThread_at_fork_reinit(PyThread_type_lock *lock)
+{
+ PyThread_type_lock new_lock = PyThread_allocate_lock();
+ if (new_lock == NULL) {
+ return -1;
+ }
+
+ /* bpo-6721, bpo-40089: The old lock can be in an inconsistent state.
+ fork() can be called in the middle of an operation on the lock done by
+ another thread. So don't call PyThread_free_lock(*lock).
+
+ Leak memory on purpose. Don't release the memory either since the
+ address of a mutex is relevant. Putting two mutexes at the same address
+ can lead to problems. */
+
+ *lock = new_lock;
+ return 0;
+}
+
+int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0, /*intr_flag=*/0);