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.
This commit is contained in:
Victor Stinner 2020-04-07 23:11:49 +02:00 committed by GitHub
parent 48b069a003
commit 87255be696
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 133 additions and 22 deletions

View file

@ -693,6 +693,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)
{