Skip to content

Commit

Permalink
review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
carljm committed Mar 4, 2023
1 parent a31af32 commit b893187
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 26 deletions.
18 changes: 11 additions & 7 deletions Doc/c-api/code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,10 @@ 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``, there may already be a pending
exception set on entry to the callback; in this case, the callback may not
execute Python code or otherwise disturb the pending exception. Taking a
reference in the callback to an about-to-be-destroyed code object will
resurrect it and prevent it from being freed.
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
Expand All @@ -187,8 +186,13 @@ bound into a function.
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 (including if an exception was already set on entry to the
callback) it should return ``0``.
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
Expand Down
19 changes: 12 additions & 7 deletions Doc/c-api/dict.rst
Original file line number Diff line number Diff line change
Expand Up @@ -301,18 +301,23 @@ Dictionary Objects
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``, there may already be a pending
exception set on entry to the callback; in this case, the callback may not
execute Python code or otherwise disturb the pending exception. Taking a new
reference in the callback to an about-to-be-destroyed dictionary will
resurrect it and prevent it from being freed.
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 sets an exception, it must return ``-1``; this exception will
be printed as an unraisable exception using :c:func:`PyErr_WriteUnraisable`.
Otherwise (including if a pending exception was already set on entry to the
callback) it should return ``0``.
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
19 changes: 11 additions & 8 deletions Doc/c-api/function.rst
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +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 *event* is ``PyFunction_EVENT_DESTROY``, there may already be a pending
exception set on entry to the callback; in this case, the callback may not
execute Python code or otherwise disturb the pending exception. Taking a
reference in the callback to an 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 the time will be called again.
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 (including if a pending exception was already set on entry to the
callback) it should return ``0``.
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
2 changes: 1 addition & 1 deletion Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,7 @@ code_dealloc(PyCodeObject *co)
Py_SET_REFCNT(co, 1);
notify_code_watchers(PY_CODE_EVENT_DESTROY, co);
if (Py_REFCNT(co) > 1) {
Py_DECREF(co);
Py_SET_REFCNT(co, Py_REFCNT(co) - 1);
return;
}
Py_SET_REFCNT(co, 0);
Expand Down
5 changes: 3 additions & 2 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2312,7 +2312,7 @@ dict_dealloc(PyDictObject *mp)
Py_SET_REFCNT(mp, 1);
_PyDict_NotifyEvent(PyDict_EVENT_DEALLOCATED, mp, NULL, NULL);
if (Py_REFCNT(mp) > 1) {
Py_DECREF(mp);
Py_SET_REFCNT(mp, Py_REFCNT(mp) - 1);
return;
}
Py_SET_REFCNT(mp, 0);
Expand Down Expand Up @@ -5755,7 +5755,8 @@ _PyDict_SendEvent(int watcher_bits,
// unraisablehook keep a reference to it, so we don't pass the
// dict as context, just an informative string message. Dict
// repr can call arbitrary code, so we invent a simpler version.
PyObject *context = PyUnicode_FromFormat("watcher callback for <dict at %p>", mp);
PyObject *context = PyUnicode_FromFormat(
"watcher callback for <dict at %p>", mp);
if (context == NULL) {
context = Py_NewRef(Py_None);
}
Expand Down
2 changes: 1 addition & 1 deletion Objects/funcobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ func_dealloc(PyFunctionObject *op)
Py_SET_REFCNT(op, 1);
handle_func_event(PyFunction_EVENT_DESTROY, op, NULL);
if (Py_REFCNT(op) > 1) {
Py_DECREF(op);
Py_SET_REFCNT(op, Py_REFCNT(op) - 1);
return;
}
Py_SET_REFCNT(op, 0);
Expand Down

0 comments on commit b893187

Please sign in to comment.