summaryrefslogtreecommitdiffstats
path: root/Doc/c-api
diff options
context:
space:
mode:
authorCarl Meyer <carl@oddbird.net>2023-03-08 00:10:58 (GMT)
committerGitHub <noreply@github.com>2023-03-08 00:10:58 (GMT)
commit1e703a473343ed198c9a06a876b25d7d69d4bbd0 (patch)
tree0ca3e31d0953a8ec475a159e19b5570e104eeefa /Doc/c-api
parenta33ca2ad1fcf857817cba505a788e15cf9d6ed0c (diff)
downloadcpython-1e703a473343ed198c9a06a876b25d7d69d4bbd0.zip
cpython-1e703a473343ed198c9a06a876b25d7d69d4bbd0.tar.gz
cpython-1e703a473343ed198c9a06a876b25d7d69d4bbd0.tar.bz2
gh-102381: don't call watcher callback with dead object (#102382)
Co-authored-by: T. Wouters <thomas@python.org>
Diffstat (limited to 'Doc/c-api')
-rw-r--r--Doc/c-api/code.rst17
-rw-r--r--Doc/c-api/dict.rst21
-rw-r--r--Doc/c-api/function.rst17
3 files changed, 45 insertions, 10 deletions
diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst
index 062ef3a..a99de99 100644
--- a/Doc/c-api/code.rst
+++ b/Doc/c-api/code.rst
@@ -172,6 +172,11 @@ bound into a function.
before the destruction of *co* takes place, so the prior state of *co*
can be inspected.
+ If *event* is ``PY_CODE_EVENT_DESTROY``, taking a reference in the callback
+ to the about-to-be-destroyed code object will resurrect it and prevent it
+ from being freed at this time. When the resurrected object is destroyed
+ later, any watcher callbacks active at that time will be called again.
+
Users of this API should not rely on internal runtime implementation
details. Such details may include, but are not limited to, the exact
order and timing of creation and destruction of code objects. While
@@ -179,9 +184,15 @@ bound into a function.
(including whether a callback is invoked or not), it does not change
the semantics of the Python code being executed.
- If the callback returns with an exception set, it must return ``-1``; this
- exception will be printed as an unraisable exception using
- :c:func:`PyErr_WriteUnraisable`. Otherwise it should return ``0``.
+ If the callback sets an exception, it must return ``-1``; this exception will
+ be printed as an unraisable exception using :c:func:`PyErr_WriteUnraisable`.
+ Otherwise it should return ``0``.
+
+ There may already be a pending exception set on entry to the callback. In
+ this case, the callback should return ``0`` with the same exception still
+ set. This means the callback may not call any other API that can set an
+ exception unless it saves and clears the exception state first, and restores
+ it before returning.
.. versionadded:: 3.12
diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst
index 34106ee..b9f84ce 100644
--- a/Doc/c-api/dict.rst
+++ b/Doc/c-api/dict.rst
@@ -298,13 +298,26 @@ Dictionary Objects
dictionary.
The callback may inspect but must not modify *dict*; doing so could have
- unpredictable effects, including infinite recursion.
+ unpredictable effects, including infinite recursion. Do not trigger Python
+ code execution in the callback, as it could modify the dict as a side effect.
+
+ If *event* is ``PyDict_EVENT_DEALLOCATED``, taking a new reference in the
+ callback to the about-to-be-destroyed dictionary will resurrect it and
+ prevent it from being freed at this time. When the resurrected object is
+ destroyed later, any watcher callbacks active at that time will be called
+ again.
Callbacks occur before the notified modification to *dict* takes place, so
the prior state of *dict* can be inspected.
- If the callback returns with an exception set, it must return ``-1``; this
- exception will be printed as an unraisable exception using
- :c:func:`PyErr_WriteUnraisable`. Otherwise it should return ``0``.
+ If the callback sets an exception, it must return ``-1``; this exception will
+ be printed as an unraisable exception using :c:func:`PyErr_WriteUnraisable`.
+ Otherwise it should return ``0``.
+
+ There may already be a pending exception set on entry to the callback. In
+ this case, the callback should return ``0`` with the same exception still
+ set. This means the callback may not call any other API that can set an
+ exception unless it saves and clears the exception state first, and restores
+ it before returning.
.. versionadded:: 3.12
diff --git a/Doc/c-api/function.rst b/Doc/c-api/function.rst
index bc7569d..947ed70 100644
--- a/Doc/c-api/function.rst
+++ b/Doc/c-api/function.rst
@@ -173,8 +173,19 @@ There are a few functions specific to Python functions.
runtime behavior depending on optimization decisions, it does not change
the semantics of the Python code being executed.
- If the callback returns with an exception set, it must return ``-1``; this
- exception will be printed as an unraisable exception using
- :c:func:`PyErr_WriteUnraisable`. Otherwise it should return ``0``.
+ If *event* is ``PyFunction_EVENT_DESTROY``, Taking a reference in the
+ callback to the about-to-be-destroyed function will resurrect it, preventing
+ it from being freed at this time. When the resurrected object is destroyed
+ later, any watcher callbacks active at that time will be called again.
+
+ If the callback sets an exception, it must return ``-1``; this exception will
+ be printed as an unraisable exception using :c:func:`PyErr_WriteUnraisable`.
+ Otherwise it should return ``0``.
+
+ There may already be a pending exception set on entry to the callback. In
+ this case, the callback should return ``0`` with the same exception still
+ set. This means the callback may not call any other API that can set an
+ exception unless it saves and clears the exception state first, and restores
+ it before returning.
.. versionadded:: 3.12