summaryrefslogtreecommitdiffstats
path: root/Include
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 /Include
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 'Include')
-rw-r--r--Include/cpython/code.h13
-rw-r--r--Include/cpython/dictobject.h21
-rw-r--r--Include/cpython/funcobject.h16
-rw-r--r--Include/internal/pycore_dict.h1
4 files changed, 31 insertions, 20 deletions
diff --git a/Include/cpython/code.h b/Include/cpython/code.h
index 0e4bd8a..abcf125 100644
--- a/Include/cpython/code.h
+++ b/Include/cpython/code.h
@@ -224,9 +224,14 @@ PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int);
PyAPI_FUNC(int) PyCode_Addr2Location(PyCodeObject *, int, int *, int *, int *, int *);
-typedef enum PyCodeEvent {
- PY_CODE_EVENT_CREATE,
- PY_CODE_EVENT_DESTROY
+#define PY_FOREACH_CODE_EVENT(V) \
+ V(CREATE) \
+ V(DESTROY)
+
+typedef enum {
+ #define PY_DEF_EVENT(op) PY_CODE_EVENT_##op,
+ PY_FOREACH_CODE_EVENT(PY_DEF_EVENT)
+ #undef PY_DEF_EVENT
} PyCodeEvent;
@@ -236,7 +241,7 @@ typedef enum PyCodeEvent {
* The callback is invoked with a borrowed reference to co, after it is
* created and before it is destroyed.
*
- * If the callback returns with an exception set, it must return -1. Otherwise
+ * If the callback sets an exception, it must return -1. Otherwise
* it should return 0.
*/
typedef int (*PyCode_WatchCallback)(
diff --git a/Include/cpython/dictobject.h b/Include/cpython/dictobject.h
index 5001f35..ddada92 100644
--- a/Include/cpython/dictobject.h
+++ b/Include/cpython/dictobject.h
@@ -16,11 +16,11 @@ typedef struct {
/* Dictionary version: globally unique, value change each time
the dictionary is modified */
-#ifdef Py_BUILD_CORE
+#ifdef Py_BUILD_CORE
uint64_t ma_version_tag;
#else
Py_DEPRECATED(3.12) uint64_t ma_version_tag;
-#endif
+#endif
PyDictKeysObject *ma_keys;
@@ -90,13 +90,18 @@ PyAPI_FUNC(PyObject *) _PyDictView_Intersect(PyObject* self, PyObject *other);
/* Dictionary watchers */
+#define PY_FOREACH_DICT_EVENT(V) \
+ V(ADDED) \
+ V(MODIFIED) \
+ V(DELETED) \
+ V(CLONED) \
+ V(CLEARED) \
+ V(DEALLOCATED)
+
typedef enum {
- PyDict_EVENT_ADDED,
- PyDict_EVENT_MODIFIED,
- PyDict_EVENT_DELETED,
- PyDict_EVENT_CLONED,
- PyDict_EVENT_CLEARED,
- PyDict_EVENT_DEALLOCATED,
+ #define PY_DEF_EVENT(EVENT) PyDict_EVENT_##EVENT,
+ PY_FOREACH_DICT_EVENT(PY_DEF_EVENT)
+ #undef PY_DEF_EVENT
} PyDict_WatchEvent;
// Callback to be invoked when a watched dict is cleared, dealloced, or modified.
diff --git a/Include/cpython/funcobject.h b/Include/cpython/funcobject.h
index 5979feb..c716330 100644
--- a/Include/cpython/funcobject.h
+++ b/Include/cpython/funcobject.h
@@ -131,17 +131,17 @@ PyAPI_DATA(PyTypeObject) PyStaticMethod_Type;
PyAPI_FUNC(PyObject *) PyClassMethod_New(PyObject *);
PyAPI_FUNC(PyObject *) PyStaticMethod_New(PyObject *);
-#define FOREACH_FUNC_EVENT(V) \
- V(CREATE) \
- V(DESTROY) \
- V(MODIFY_CODE) \
- V(MODIFY_DEFAULTS) \
+#define PY_FOREACH_FUNC_EVENT(V) \
+ V(CREATE) \
+ V(DESTROY) \
+ V(MODIFY_CODE) \
+ V(MODIFY_DEFAULTS) \
V(MODIFY_KWDEFAULTS)
typedef enum {
- #define DEF_EVENT(EVENT) PyFunction_EVENT_##EVENT,
- FOREACH_FUNC_EVENT(DEF_EVENT)
- #undef DEF_EVENT
+ #define PY_DEF_EVENT(EVENT) PyFunction_EVENT_##EVENT,
+ PY_FOREACH_FUNC_EVENT(PY_DEF_EVENT)
+ #undef PY_DEF_EVENT
} PyFunction_WatchEvent;
/*
diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h
index c74a343..1af5e59 100644
--- a/Include/internal/pycore_dict.h
+++ b/Include/internal/pycore_dict.h
@@ -164,6 +164,7 @@ _PyDict_NotifyEvent(PyDict_WatchEvent event,
PyObject *key,
PyObject *value)
{
+ assert(Py_REFCNT((PyObject*)mp) > 0);
int watcher_bits = mp->ma_version_tag & DICT_VERSION_MASK;
if (watcher_bits) {
_PyDict_SendEvent(watcher_bits, event, mp, key, value);