directly rather than through :func:`os.fork` (and returning to or calling
into Python) may result in a deadlock by one of Python's internal locks
being held by a thread that is defunct after the fork.
-:c:func:`PyOS_AfterFork` tries to reset the necessary locks, but is not
+:c:func:`PyOS_AfterFork_Child` tries to reset the necessary locks, but is not
always able to.
.. c:function:: void PyEval_ReInitThreads()
- This function is called from :c:func:`PyOS_AfterFork` to ensure that newly
- created child processes don't hold locks referring to threads which
- are not running in the child process.
+ This function is called from :c:func:`PyOS_AfterFork_Child` to ensure
+ that newly created child processes don't hold locks referring to threads
+ which are not running in the child process.
The following functions use thread-local storage, and are not compatible
Added support for :ref:`file descriptors <path_fd>` in :func:`~os.scandir`
on Unix. (Contributed by Serhiy Storchaka in :issue:`25996`.)
+New function :func:`os.register_at_fork` allows registering Python callbacks
+to be executed on a process fork. (Contributed by Antoine Pitrou in
+:issue:`16500`.)
+
unittest.mock
-------------
* Added functions :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`.
(Contributed by Serhiy Storchaka in :issue:`27867`.)
+* :c:func:`PyOS_AfterFork` is deprecated in favour of the new functions
+ :c:func:`PyOS_BeforeFork`, :c:func:`PyOS_AfterFork_Parent` and
+ :c:func:`PyOS_AfterFork_Child`. (Contributed by Antoine Pitrou in
+ :issue:`16500`.)
+
Deprecated
==========
def _after_fork():
# This function is called by Python/ceval.c:PyEval_ReInitThreads which
- # is called from PyOS_AfterFork. Here we cleanup threading module state
- # that should not exist after a fork.
+ # is called from PyOS_AfterFork_Child. Here we cleanup threading module
+ # state that should not exist after a fork.
# Reset _active_limbo_lock, in case we forked while the lock was held
# by another (non-forked) thread. http://bugs.python.org/issue874900
C API
-----
+- bpo-16500: Deprecate PyOS_AfterFork() and add PyOS_BeforeFork(),
+ PyOS_AfterFork_Parent() and PyOS_AfterFork_Child().
+
- bpo-6532: The type of results of PyThread_start_new_thread() and
PyThread_get_thread_ident(), and the id parameter of
PyThreadState_SetAsyncExc() changed from "long" to "unsigned long".
drop_gil(tstate);
}
-/* This function is called from PyOS_AfterFork to destroy all threads which are
- * not running in the child process, and clear internal locks which might be
- * held by those threads. (This could also be done using pthread_atfork
- * mechanism, at least for the pthreads implementation.) */
+/* This function is called from PyOS_AfterFork_Child to destroy all threads
+ * which are not running in the child process, and clear internal locks
+ * which might be held by those threads.
+ */
void
PyEval_ReInitThreads(void)
return 1;
}
-/* This function is called from PyOS_AfterFork to ensure that newly
+/* This function is called from PyOS_AfterFork_Child to ensure that newly
created child processes do not share locks with the parent.
We now acquire the import lock around fork() calls but on some platforms
(Solaris 9 and earlier? see isue7242) that still left us with problems. */
autoInterpreterState = NULL;
}
-/* Reset the TLS key - called by PyOS_AfterFork().
+/* Reset the TLS key - called by PyOS_AfterFork_Child().
* This should not be necessary, but some - buggy - pthread implementations
* don't reset TLS upon fork(), see issue #10517.
*/
}
/* Forget everything not associated with the current thread id.
- * This function is called from PyOS_AfterFork(). It is necessary
+ * This function is called from PyOS_AfterFork_Child(). It is necessary
* because other thread ids which were in use at the time of the fork
* may be reused for new threads created in the forked process.
*/