aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_collectionsmodule.c5
-rw-r--r--Modules/_datetimemodule.c2
-rw-r--r--Modules/_elementtree.c4
-rw-r--r--Modules/_functoolsmodule.c9
-rw-r--r--Modules/_heapqmodule.c6
-rw-r--r--Modules/_io/bufferedio.c7
-rw-r--r--Modules/_io/bytesio.c4
-rw-r--r--Modules/_io/fileio.c5
-rw-r--r--Modules/_io/iobase.c4
-rw-r--r--Modules/_io/stringio.c5
-rw-r--r--Modules/_io/textio.c4
-rw-r--r--Modules/_io/winconsoleio.c4
-rw-r--r--Modules/_localemodule.c2
-rw-r--r--Modules/_queuemodule.c5
-rw-r--r--Modules/_remote_debugging_module.c83
-rw-r--r--Modules/_sqlite/blob.c5
-rw-r--r--Modules/_sqlite/cursor.c5
-rw-r--r--Modules/_sre/sre.c6
-rw-r--r--Modules/_stat.c4
-rw-r--r--Modules/_struct.c5
-rw-r--r--Modules/_testcapi/abstract.c38
-rw-r--r--Modules/_testcapi/vectorcall.c8
-rw-r--r--Modules/_testinternalcapi.c2
-rw-r--r--Modules/_threadmodule.c22
-rw-r--r--Modules/_zoneinfo.c5
-rw-r--r--Modules/arraymodule.c5
-rw-r--r--Modules/blake2module.c66
-rw-r--r--Modules/clinic/_remote_debugging_module.c.h40
-rw-r--r--Modules/clinic/mathmodule.c.h36
-rw-r--r--Modules/getpath.py11
-rw-r--r--Modules/hmacmodule.c21
-rw-r--r--Modules/itertoolsmodule.c38
-rw-r--r--Modules/mathmodule.c18
-rw-r--r--Modules/mmapmodule.c4
-rw-r--r--Modules/pyexpat.c85
35 files changed, 415 insertions, 158 deletions
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index ad670293ec5..3ba48d5d9d3 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -5,6 +5,7 @@
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_pyatomic_ft_wrappers.h"
#include "pycore_typeobject.h" // _PyType_GetModuleState()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stddef.h>
@@ -1532,9 +1533,7 @@ deque_dealloc(PyObject *self)
Py_ssize_t i;
PyObject_GC_UnTrack(deque);
- if (deque->weakreflist != NULL) {
- PyObject_ClearWeakRefs(self);
- }
+ FT_CLEAR_WEAKREFS(self, deque->weakreflist);
if (deque->leftblock != NULL) {
(void)deque_clear(self);
assert(deque->leftblock != NULL);
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index eb90be81c8d..7a6426593d0 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -1934,7 +1934,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
}
replacement = freplacement;
}
-#ifdef Py_NORMALIZE_CENTURY
+#ifdef _Py_NORMALIZE_CENTURY
else if (ch == 'Y' || ch == 'G'
|| ch == 'F' || ch == 'C'
) {
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index fe24629f9f6..b9e12ab2026 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -17,6 +17,7 @@
#include "Python.h"
#include "pycore_pyhash.h" // _Py_HashSecret
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stddef.h> // offsetof()
#include "expat.h"
@@ -690,8 +691,7 @@ element_dealloc(PyObject *op)
/* bpo-31095: UnTrack is needed before calling any callbacks */
PyObject_GC_UnTrack(self);
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs(op);
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
/* element_gc_clear clears all references and deallocates extra
*/
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 354dbad84b5..d3dabd58b89 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -7,6 +7,7 @@
#include "pycore_pyatomic_ft_wrappers.h"
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_tuple.h" // _PyTuple_ITEMS()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include "clinic/_functoolsmodule.c.h"
@@ -351,9 +352,7 @@ partial_dealloc(PyObject *self)
PyTypeObject *tp = Py_TYPE(self);
/* bpo-31095: UnTrack is needed before calling any callbacks */
PyObject_GC_UnTrack(self);
- if (partialobject_CAST(self)->weakreflist != NULL) {
- PyObject_ClearWeakRefs(self);
- }
+ FT_CLEAR_WEAKREFS(self, partialobject_CAST(self)->weakreflist);
(void)partial_clear(self);
tp->tp_free(self);
Py_DECREF(tp);
@@ -1621,9 +1620,7 @@ lru_cache_dealloc(PyObject *op)
PyTypeObject *tp = Py_TYPE(obj);
/* bpo-31095: UnTrack is needed before calling any callbacks */
PyObject_GC_UnTrack(obj);
- if (obj->weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, obj->weakreflist);
(void)lru_cache_tp_clear(op);
tp->tp_free(obj);
diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c
index 560fe431fca..05d01acd771 100644
--- a/Modules/_heapqmodule.c
+++ b/Modules/_heapqmodule.c
@@ -463,11 +463,11 @@ siftup_max(PyListObject *heap, Py_ssize_t pos)
return -1;
}
- /* Bubble up the smaller child until hitting a leaf. */
+ /* Bubble up the larger child until hitting a leaf. */
arr = _PyList_ITEMS(heap);
limit = endpos >> 1; /* smallest pos that has no child */
while (pos < limit) {
- /* Set childpos to index of smaller child. */
+ /* Set childpos to index of larger child. */
childpos = 2*pos + 1; /* leftmost child position */
if (childpos + 1 < endpos) {
PyObject* a = arr[childpos + 1];
@@ -487,7 +487,7 @@ siftup_max(PyListObject *heap, Py_ssize_t pos)
return -1;
}
}
- /* Move the smaller child up. */
+ /* Move the larger child up. */
tmp1 = arr[childpos];
tmp2 = arr[pos];
FT_ATOMIC_STORE_PTR_RELAXED(arr[childpos], tmp2);
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 4724e97982f..25c8bf8b3d5 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -13,6 +13,7 @@
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pyerrors.h" // _Py_FatalErrorFormat()
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include "_iomodule.h"
@@ -421,8 +422,7 @@ buffered_dealloc(PyObject *op)
return;
_PyObject_GC_UNTRACK(self);
self->ok = 0;
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs(op);
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
if (self->buffer) {
PyMem_Free(self->buffer);
self->buffer = NULL;
@@ -2312,8 +2312,7 @@ bufferedrwpair_dealloc(PyObject *op)
rwpair *self = rwpair_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
_PyObject_GC_UNTRACK(self);
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs(op);
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
(void)bufferedrwpair_clear(op);
tp->tp_free(self);
Py_DECREF(tp);
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 61cfec435fe..1c71bce4fbb 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -3,6 +3,7 @@
#include "pycore_object.h"
#include "pycore_pyatomic_ft_wrappers.h"
#include "pycore_sysmodule.h" // _PySys_GetSizeOf()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stddef.h> // offsetof()
#include "_iomodule.h"
@@ -979,8 +980,7 @@ bytesio_dealloc(PyObject *op)
}
Py_CLEAR(self->buf);
Py_CLEAR(self->dict);
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs(op);
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
tp->tp_free(self);
Py_DECREF(tp);
}
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 8fcb27049d6..26537fc6395 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -4,6 +4,7 @@
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stdbool.h> // bool
#ifdef HAVE_UNISTD_H
@@ -570,9 +571,7 @@ fileio_dealloc(PyObject *op)
PyMem_Free(self->stat_atopen);
self->stat_atopen = NULL;
}
- if (self->weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
(void)fileio_clear(op);
PyTypeObject *tp = Py_TYPE(op);
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index cd4c7e7cead..044f6b7803c 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -14,6 +14,7 @@
#include "pycore_long.h" // _PyLong_GetOne()
#include "pycore_object.h" // _PyType_HasFeature()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stddef.h> // offsetof()
#include "_iomodule.h"
@@ -383,8 +384,7 @@ iobase_dealloc(PyObject *op)
}
PyTypeObject *tp = Py_TYPE(self);
_PyObject_GC_UNTRACK(self);
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs(op);
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
Py_CLEAR(self->dict);
tp->tp_free(self);
Py_DECREF(tp);
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index 56913fafefb..20b7cfc0088 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -1,6 +1,7 @@
#include "Python.h"
#include <stddef.h> // offsetof()
#include "pycore_object.h"
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include "_iomodule.h"
/* Implementation note: the buffer is always at least one character longer
@@ -638,9 +639,7 @@ stringio_dealloc(PyObject *op)
}
PyUnicodeWriter_Discard(self->writer);
(void)stringio_clear(op);
- if (self->weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
tp->tp_free(self);
Py_DECREF(tp);
}
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 3808ecdceb9..5354cf63442 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -16,6 +16,7 @@
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_unicodeobject.h" // _PyUnicode_AsASCIIString()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include "_iomodule.h"
@@ -1469,8 +1470,7 @@ textiowrapper_dealloc(PyObject *op)
return;
self->ok = 0;
_PyObject_GC_UNTRACK(self);
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs(op);
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
(void)textiowrapper_clear(op);
tp->tp_free(self);
Py_DECREF(tp);
diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c
index 3e783b9da45..950b7fe241c 100644
--- a/Modules/_io/winconsoleio.c
+++ b/Modules/_io/winconsoleio.c
@@ -10,6 +10,7 @@
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#ifdef HAVE_WINDOWS_CONSOLE_IO
@@ -518,8 +519,7 @@ winconsoleio_dealloc(PyObject *op)
if (_PyIOBase_finalize(op) < 0)
return;
_PyObject_GC_UNTRACK(self);
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs(op);
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
Py_CLEAR(self->dict);
tp->tp_free(self);
Py_DECREF(tp);
diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c
index c1f56008b7c..41e6d48b1db 100644
--- a/Modules/_localemodule.c
+++ b/Modules/_localemodule.c
@@ -692,7 +692,7 @@ _locale_nl_langinfo_impl(PyObject *module, int item)
result = result != NULL ? result : "";
char *oldloc = NULL;
if (langinfo_constants[i].category != LC_CTYPE
- && (
+ && *result && (
#ifdef __GLIBC__
// gh-133740: Always change the locale for ALT_DIGITS and ERA
# ifdef ALT_DIGITS
diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c
index 3ee14b61b82..01235c77bd7 100644
--- a/Modules/_queuemodule.c
+++ b/Modules/_queuemodule.c
@@ -7,6 +7,7 @@
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_parking_lot.h"
#include "pycore_time.h" // _PyTime_FromSecondsObject()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stdbool.h>
#include <stddef.h> // offsetof()
@@ -221,9 +222,7 @@ simplequeue_dealloc(PyObject *op)
PyObject_GC_UnTrack(self);
(void)simplequeue_clear(op);
- if (self->weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
tp->tp_free(self);
Py_DECREF(tp);
}
diff --git a/Modules/_remote_debugging_module.c b/Modules/_remote_debugging_module.c
index c2421cac6bd..ce7189637c2 100644
--- a/Modules/_remote_debugging_module.c
+++ b/Modules/_remote_debugging_module.c
@@ -64,12 +64,14 @@
#endif
#ifdef Py_GIL_DISABLED
-#define INTERP_STATE_MIN_SIZE MAX(MAX(offsetof(PyInterpreterState, _code_object_generation) + sizeof(uint64_t), \
- offsetof(PyInterpreterState, tlbc_indices.tlbc_generation) + sizeof(uint32_t)), \
- offsetof(PyInterpreterState, threads.head) + sizeof(void*))
+#define INTERP_STATE_MIN_SIZE MAX(MAX(MAX(offsetof(PyInterpreterState, _code_object_generation) + sizeof(uint64_t), \
+ offsetof(PyInterpreterState, tlbc_indices.tlbc_generation) + sizeof(uint32_t)), \
+ offsetof(PyInterpreterState, threads.head) + sizeof(void*)), \
+ offsetof(PyInterpreterState, _gil.last_holder) + sizeof(PyThreadState*))
#else
-#define INTERP_STATE_MIN_SIZE MAX(offsetof(PyInterpreterState, _code_object_generation) + sizeof(uint64_t), \
- offsetof(PyInterpreterState, threads.head) + sizeof(void*))
+#define INTERP_STATE_MIN_SIZE MAX(MAX(offsetof(PyInterpreterState, _code_object_generation) + sizeof(uint64_t), \
+ offsetof(PyInterpreterState, threads.head) + sizeof(void*)), \
+ offsetof(PyInterpreterState, _gil.last_holder) + sizeof(PyThreadState*))
#endif
#define INTERP_STATE_BUFFER_SIZE MAX(INTERP_STATE_MIN_SIZE, 256)
@@ -206,6 +208,7 @@ typedef struct {
uint64_t code_object_generation;
_Py_hashtable_t *code_object_cache;
int debug;
+ int only_active_thread;
RemoteDebuggingState *cached_state; // Cached module state
#ifdef Py_GIL_DISABLED
// TLBC cache invalidation tracking
@@ -2496,6 +2499,7 @@ _remote_debugging.RemoteUnwinder.__init__
pid: int
*
all_threads: bool = False
+ only_active_thread: bool = False
debug: bool = False
Initialize a new RemoteUnwinder object for debugging a remote Python process.
@@ -2504,6 +2508,8 @@ Args:
pid: Process ID of the target Python process to debug
all_threads: If True, initialize state for all threads in the process.
If False, only initialize for the main thread.
+ only_active_thread: If True, only sample the thread holding the GIL.
+ Cannot be used together with all_threads=True.
debug: If True, chain exceptions to explain the sequence of events that
lead to the exception.
@@ -2514,15 +2520,33 @@ Raises:
PermissionError: If access to the target process is denied
OSError: If unable to attach to the target process or access its memory
RuntimeError: If unable to read debug information from the target process
+ ValueError: If both all_threads and only_active_thread are True
[clinic start generated code]*/
static int
_remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self,
int pid, int all_threads,
+ int only_active_thread,
int debug)
-/*[clinic end generated code: output=3982f2a7eba49334 input=48a762566b828e91]*/
+/*[clinic end generated code: output=13ba77598ecdcbe1 input=8f8f12504e17da04]*/
{
+ // Validate that all_threads and only_active_thread are not both True
+ if (all_threads && only_active_thread) {
+ PyErr_SetString(PyExc_ValueError,
+ "all_threads and only_active_thread cannot both be True");
+ return -1;
+ }
+
+#ifdef Py_GIL_DISABLED
+ if (only_active_thread) {
+ PyErr_SetString(PyExc_ValueError,
+ "only_active_thread is not supported when Py_GIL_DISABLED is not defined");
+ return -1;
+ }
+#endif
+
self->debug = debug;
+ self->only_active_thread = only_active_thread;
self->cached_state = NULL;
if (_Py_RemoteDebug_InitProcHandle(&self->handle, pid) < 0) {
set_exception_cause(self, PyExc_RuntimeError, "Failed to initialize process handle");
@@ -2602,13 +2626,18 @@ _remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self,
@critical_section
_remote_debugging.RemoteUnwinder.get_stack_trace
-Returns a list of stack traces for all threads in the target process.
+Returns a list of stack traces for threads in the target process.
Each element in the returned list is a tuple of (thread_id, frame_list), where:
- thread_id is the OS thread identifier
- frame_list is a list of tuples (function_name, filename, line_number) representing
the Python stack frames for that thread, ordered from most recent to oldest
+The threads returned depend on the initialization parameters:
+- If only_active_thread was True: returns only the thread holding the GIL
+- If all_threads was True: returns all threads
+- Otherwise: returns only the main thread
+
Example:
[
(1234, [
@@ -2632,7 +2661,7 @@ Raises:
static PyObject *
_remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self)
-/*[clinic end generated code: output=666192b90c69d567 input=331dbe370578badf]*/
+/*[clinic end generated code: output=666192b90c69d567 input=f756f341206f9116]*/
{
PyObject* result = NULL;
// Read interpreter state into opaque buffer
@@ -2655,6 +2684,28 @@ _remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self
_Py_hashtable_clear(self->code_object_cache);
}
+ // If only_active_thread is true, we need to determine which thread holds the GIL
+ PyThreadState* gil_holder = NULL;
+ if (self->only_active_thread) {
+ // The GIL state is already in interp_state_buffer, just read from there
+ // Check if GIL is locked
+ int gil_locked = GET_MEMBER(int, interp_state_buffer,
+ self->debug_offsets.interpreter_state.gil_runtime_state_locked);
+
+ if (gil_locked) {
+ // Get the last holder (current holder when GIL is locked)
+ gil_holder = GET_MEMBER(PyThreadState*, interp_state_buffer,
+ self->debug_offsets.interpreter_state.gil_runtime_state_holder);
+ } else {
+ // GIL is not locked, return empty list
+ result = PyList_New(0);
+ if (!result) {
+ set_exception_cause(self, PyExc_MemoryError, "Failed to create empty result list");
+ }
+ goto exit;
+ }
+ }
+
#ifdef Py_GIL_DISABLED
// Check TLBC generation and invalidate cache if needed
uint32_t current_tlbc_generation = GET_MEMBER(uint32_t, interp_state_buffer,
@@ -2666,7 +2717,10 @@ _remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self
#endif
uintptr_t current_tstate;
- if (self->tstate_addr == 0) {
+ if (self->only_active_thread && gil_holder != NULL) {
+ // We have the GIL holder, process only that thread
+ current_tstate = (uintptr_t)gil_holder;
+ } else if (self->tstate_addr == 0) {
// Get threads head from buffer
current_tstate = GET_MEMBER(uintptr_t, interp_state_buffer,
self->debug_offsets.interpreter_state.threads_head);
@@ -2700,10 +2754,14 @@ _remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self
if (self->tstate_addr) {
break;
}
+
+ // If we're only processing the GIL holder, we're done after one iteration
+ if (self->only_active_thread && gil_holder != NULL) {
+ break;
+ }
}
exit:
- _Py_RemoteDebug_ClearCache(&self->handle);
return result;
}
@@ -2827,11 +2885,9 @@ _remote_debugging_RemoteUnwinder_get_all_awaited_by_impl(RemoteUnwinderObject *s
goto result_err;
}
- _Py_RemoteDebug_ClearCache(&self->handle);
return result;
result_err:
- _Py_RemoteDebug_ClearCache(&self->handle);
Py_XDECREF(result);
return NULL;
}
@@ -2898,11 +2954,9 @@ _remote_debugging_RemoteUnwinder_get_async_stack_trace_impl(RemoteUnwinderObject
goto cleanup;
}
- _Py_RemoteDebug_ClearCache(&self->handle);
return result;
cleanup:
- _Py_RemoteDebug_ClearCache(&self->handle);
Py_XDECREF(result);
return NULL;
}
@@ -2928,7 +2982,6 @@ RemoteUnwinder_dealloc(PyObject *op)
}
#endif
if (self->handle.pid != 0) {
- _Py_RemoteDebug_ClearCache(&self->handle);
_Py_RemoteDebug_CleanupProcHandle(&self->handle);
}
PyObject_Del(self);
diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c
index 35d090e3ca2..aafefbf316e 100644
--- a/Modules/_sqlite/blob.c
+++ b/Modules/_sqlite/blob.c
@@ -4,6 +4,7 @@
#include "blob.h"
#include "util.h"
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#define clinic_state() (pysqlite_get_state_by_type(Py_TYPE(self)))
#include "clinic/blob.c.h"
@@ -56,9 +57,7 @@ blob_dealloc(PyObject *op)
close_blob(self);
- if (self->in_weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, self->in_weakreflist);
(void)tp->tp_clear(op);
tp->tp_free(self);
Py_DECREF(tp);
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index 7943bfcca36..0c3f43d0e50 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -31,6 +31,7 @@
#include "util.h"
#include "pycore_pyerrors.h" // _PyErr_FormatFromCause()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
typedef enum {
TYPE_LONG,
@@ -185,9 +186,7 @@ cursor_dealloc(PyObject *op)
pysqlite_Cursor *self = _pysqlite_Cursor_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
- if (self->in_weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, self->in_weakreflist);
(void)tp->tp_clear(op);
tp->tp_free(self);
Py_DECREF(tp);
diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c
index 602d0ab8588..e8943920043 100644
--- a/Modules/_sre/sre.c
+++ b/Modules/_sre/sre.c
@@ -44,6 +44,7 @@ static const char copyright[] =
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_unicodeobject.h" // _PyUnicode_Copy
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include "sre.h" // SRE_CODE
@@ -736,10 +737,7 @@ pattern_dealloc(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
- PatternObject *obj = _PatternObject_CAST(self);
- if (obj->weakreflist != NULL) {
- PyObject_ClearWeakRefs(self);
- }
+ FT_CLEAR_WEAKREFS(self, _PatternObject_CAST(self)->weakreflist);
(void)pattern_clear(self);
tp->tp_free(self);
Py_DECREF(tp);
diff --git a/Modules/_stat.c b/Modules/_stat.c
index f11ca7d23b4..1dabf2f6d5b 100644
--- a/Modules/_stat.c
+++ b/Modules/_stat.c
@@ -57,7 +57,7 @@ typedef unsigned short mode_t;
* Only the names are defined by POSIX but not their value. All common file
* types seems to have the same numeric value on all platforms, though.
*
- * pyport.h guarantees S_IFMT, S_IFDIR, S_IFCHR, S_IFREG and S_IFLNK
+ * fileutils.h guarantees S_IFMT, S_IFDIR, S_IFCHR, S_IFREG and S_IFLNK
*/
#ifndef S_IFBLK
@@ -86,7 +86,7 @@ typedef unsigned short mode_t;
/* S_ISXXX()
- * pyport.h defines S_ISDIR(), S_ISREG() and S_ISCHR()
+ * fileutils.h defines S_ISDIR(), S_ISREG() and S_ISCHR()
*/
#ifndef S_ISBLK
diff --git a/Modules/_struct.c b/Modules/_struct.c
index c36079f1eb8..3fad35a8c94 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -11,6 +11,7 @@
#include "pycore_bytesobject.h" // _PyBytesWriter
#include "pycore_long.h" // _PyLong_AsByteArray()
#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stddef.h> // offsetof()
@@ -1794,9 +1795,7 @@ s_dealloc(PyObject *op)
PyStructObject *s = PyStructObject_CAST(op);
PyTypeObject *tp = Py_TYPE(s);
PyObject_GC_UnTrack(s);
- if (s->weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, s->weakreflist);
if (s->s_codes != NULL) {
PyMem_Free(s->s_codes);
}
diff --git a/Modules/_testcapi/abstract.c b/Modules/_testcapi/abstract.c
index d4045afd515..c1f769456ac 100644
--- a/Modules/_testcapi/abstract.c
+++ b/Modules/_testcapi/abstract.c
@@ -178,6 +178,42 @@ sequence_fast_get_item(PyObject *self, PyObject *args)
}
+static PyObject *
+object_setattr_null_exc(PyObject *self, PyObject *args)
+{
+ PyObject *obj, *name, *exc;
+ if (!PyArg_ParseTuple(args, "OOO", &obj, &name, &exc)) {
+ return NULL;
+ }
+
+ PyErr_SetObject((PyObject*)Py_TYPE(exc), exc);
+ if (PyObject_SetAttr(obj, name, NULL) < 0) {
+ return NULL;
+ }
+ assert(PyErr_Occurred());
+ return NULL;
+}
+
+
+static PyObject *
+object_setattrstring_null_exc(PyObject *self, PyObject *args)
+{
+ PyObject *obj, *exc;
+ const char *name;
+ Py_ssize_t size;
+ if (!PyArg_ParseTuple(args, "Oz#O", &obj, &name, &size, &exc)) {
+ return NULL;
+ }
+
+ PyErr_SetObject((PyObject*)Py_TYPE(exc), exc);
+ if (PyObject_SetAttrString(obj, name, NULL) < 0) {
+ return NULL;
+ }
+ assert(PyErr_Occurred());
+ return NULL;
+}
+
+
static PyMethodDef test_methods[] = {
{"object_getoptionalattr", object_getoptionalattr, METH_VARARGS},
{"object_getoptionalattrstring", object_getoptionalattrstring, METH_VARARGS},
@@ -191,6 +227,8 @@ static PyMethodDef test_methods[] = {
{"sequence_fast_get_size", sequence_fast_get_size, METH_O},
{"sequence_fast_get_item", sequence_fast_get_item, METH_VARARGS},
+ {"object_setattr_null_exc", object_setattr_null_exc, METH_VARARGS},
+ {"object_setattrstring_null_exc", object_setattrstring_null_exc, METH_VARARGS},
{NULL},
};
diff --git a/Modules/_testcapi/vectorcall.c b/Modules/_testcapi/vectorcall.c
index 03aaacb328e..f89dcb6c4cf 100644
--- a/Modules/_testcapi/vectorcall.c
+++ b/Modules/_testcapi/vectorcall.c
@@ -179,14 +179,14 @@ _testcapi_VectorCallClass_set_vectorcall_impl(PyObject *self,
if (!PyObject_TypeCheck(self, type)) {
return PyErr_Format(
PyExc_TypeError,
- "expected %s instance",
- PyType_GetName(type));
+ "expected %N instance",
+ type);
}
if (!type->tp_vectorcall_offset) {
return PyErr_Format(
PyExc_TypeError,
- "type %s has no vectorcall offset",
- PyType_GetName(type));
+ "type %N has no vectorcall offset",
+ type);
}
*(vectorcallfunc*)((char*)self + type->tp_vectorcall_offset) = (
VectorCallClass_vectorcall);
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index fdf22a0c994..8027f0015c7 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -121,7 +121,7 @@ get_c_recursion_remaining(PyObject *self, PyObject *Py_UNUSED(args))
PyThreadState *tstate = _PyThreadState_GET();
uintptr_t here_addr = _Py_get_machine_stack_pointer();
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
- int remaining = (int)((here_addr - _tstate->c_stack_soft_limit)/PYOS_STACK_MARGIN_BYTES * 50);
+ int remaining = (int)((here_addr - _tstate->c_stack_soft_limit) / _PyOS_STACK_MARGIN_BYTES * 50);
return PyLong_FromLong(remaining);
}
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 150a266b521..8886a9d6bd0 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -834,9 +834,14 @@ lock_PyThread_acquire_lock(PyObject *op, PyObject *args, PyObject *kwds)
return NULL;
}
- PyLockStatus r = _PyMutex_LockTimed(&self->lock, timeout,
- _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
+ PyLockStatus r = _PyMutex_LockTimed(
+ &self->lock, timeout,
+ _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
if (r == PY_LOCK_INTR) {
+ assert(PyErr_Occurred());
+ return NULL;
+ }
+ if (r == PY_LOCK_FAILURE && PyErr_Occurred()) {
return NULL;
}
@@ -1054,9 +1059,14 @@ rlock_acquire(PyObject *op, PyObject *args, PyObject *kwds)
return NULL;
}
- PyLockStatus r = _PyRecursiveMutex_LockTimed(&self->lock, timeout,
- _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
+ PyLockStatus r = _PyRecursiveMutex_LockTimed(
+ &self->lock, timeout,
+ _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
if (r == PY_LOCK_INTR) {
+ assert(PyErr_Occurred());
+ return NULL;
+ }
+ if (r == PY_LOCK_FAILURE && PyErr_Occurred()) {
return NULL;
}
@@ -1365,9 +1375,7 @@ static void
localdummy_dealloc(PyObject *op)
{
localdummyobject *self = localdummyobject_CAST(op);
- if (self->weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
PyTypeObject *tp = Py_TYPE(self);
tp->tp_free(self);
Py_DECREF(tp);
diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c
index abd53436b21..5c5383d260a 100644
--- a/Modules/_zoneinfo.c
+++ b/Modules/_zoneinfo.c
@@ -7,6 +7,7 @@
#include "pycore_long.h" // _PyLong_GetOne()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_typeobject.h" // _PyType_GetModuleState()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include "datetime.h" // PyDateTime_TZInfo
@@ -375,9 +376,7 @@ zoneinfo_dealloc(PyObject *obj_self)
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
- if (self->weakreflist != NULL) {
- PyObject_ClearWeakRefs(obj_self);
- }
+ FT_CLEAR_WEAKREFS(obj_self, self->weakreflist);
if (self->trans_list_utc != NULL) {
PyMem_Free(self->trans_list_utc);
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 401a3a7072b..5d07de2fba9 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -13,6 +13,7 @@
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
#include "pycore_modsupport.h" // _PyArg_NoKeywords()
#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stddef.h> // offsetof()
#include <stdbool.h>
@@ -728,9 +729,7 @@ array_dealloc(PyObject *op)
PyObject_GC_UnTrack(op);
arrayobject *self = arrayobject_CAST(op);
- if (self->weakreflist != NULL) {
- PyObject_ClearWeakRefs(op);
- }
+ FT_CLEAR_WEAKREFS(op, self->weakreflist);
if (self->ob_item != NULL) {
PyMem_Free(self->ob_item);
}
diff --git a/Modules/blake2module.c b/Modules/blake2module.c
index 9e279e11b51..163f238a426 100644
--- a/Modules/blake2module.c
+++ b/Modules/blake2module.c
@@ -43,25 +43,25 @@
// SIMD256 can't be compiled on macOS ARM64, and performance of SIMD128 isn't
// great; but when compiling a universal2 binary, autoconf will set
-// HACL_CAN_COMPILE_SIMD128 and HACL_CAN_COMPILE_SIMD256 because they *can* be
-// compiled on x86_64. If we're on macOS ARM64, disable these preprocessor
-// symbols.
+// _Py_HACL_CAN_COMPILE_VEC{128,256} because they *can* be compiled on x86_64.
+// If we're on macOS ARM64, we however disable these preprocessor symbols.
#if defined(__APPLE__) && defined(__arm64__)
-# undef HACL_CAN_COMPILE_SIMD128
-# undef HACL_CAN_COMPILE_SIMD256
+# undef _Py_HACL_CAN_COMPILE_VEC128
+# undef _Py_HACL_CAN_COMPILE_VEC256
#endif
-// Small mismatch between the variable names Python defines as part of configure
-// at the ones HACL* expects to be set in order to enable those headers.
-#define HACL_CAN_COMPILE_VEC128 HACL_CAN_COMPILE_SIMD128
-#define HACL_CAN_COMPILE_VEC256 HACL_CAN_COMPILE_SIMD256
+// HACL* expects HACL_CAN_COMPILE_VEC* macros to be set in order to enable
+// the corresponding SIMD instructions so we need to "forward" the values
+// we just deduced above.
+#define HACL_CAN_COMPILE_VEC128 _Py_HACL_CAN_COMPILE_VEC128
+#define HACL_CAN_COMPILE_VEC256 _Py_HACL_CAN_COMPILE_VEC256
#include "_hacl/Hacl_Hash_Blake2s.h"
#include "_hacl/Hacl_Hash_Blake2b.h"
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
#include "_hacl/Hacl_Hash_Blake2s_Simd128.h"
#endif
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
#include "_hacl/Hacl_Hash_Blake2b_Simd256.h"
#endif
@@ -88,7 +88,7 @@ blake2_get_state(PyObject *module)
return (Blake2State *)state;
}
-#if defined(HACL_CAN_COMPILE_SIMD128) || defined(HACL_CAN_COMPILE_SIMD256)
+#if defined(_Py_HACL_CAN_COMPILE_VEC128) || defined(_Py_HACL_CAN_COMPILE_VEC256)
static inline Blake2State *
blake2_get_state_from_type(PyTypeObject *module)
{
@@ -181,7 +181,7 @@ blake2module_init_cpu_features(Blake2State *state)
#undef ECX_SSE3
#undef EBX_AVX2
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
// TODO(picnixz): use py_cpuid_features (gh-125022) to improve detection
state->can_run_simd128 = sse && sse2 && sse3 && sse41 && sse42 && cmov;
#else
@@ -191,7 +191,7 @@ blake2module_init_cpu_features(Blake2State *state)
state->can_run_simd128 = false;
#endif
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
// TODO(picnixz): use py_cpuid_features (gh-125022) to improve detection
state->can_run_simd256 = state->can_run_simd128 && avx && avx2;
#else
@@ -332,18 +332,18 @@ is_blake2s(blake2_impl impl)
static inline blake2_impl
type_to_impl(PyTypeObject *type)
{
-#if defined(HACL_CAN_COMPILE_SIMD128) || defined(HACL_CAN_COMPILE_SIMD256)
+#if defined(_Py_HACL_CAN_COMPILE_VEC128) || defined(_Py_HACL_CAN_COMPILE_VEC256)
Blake2State *st = blake2_get_state_from_type(type);
#endif
if (!strcmp(type->tp_name, blake2b_type_spec.name)) {
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
return st->can_run_simd256 ? Blake2b_256 : Blake2b;
#else
return Blake2b;
#endif
}
else if (!strcmp(type->tp_name, blake2s_type_spec.name)) {
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
return st->can_run_simd128 ? Blake2s_128 : Blake2s;
#else
return Blake2s;
@@ -357,10 +357,10 @@ typedef struct {
union {
Hacl_Hash_Blake2s_state_t *blake2s_state;
Hacl_Hash_Blake2b_state_t *blake2b_state;
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
Hacl_Hash_Blake2s_Simd128_state_t *blake2s_128_state;
#endif
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
Hacl_Hash_Blake2b_Simd256_state_t *blake2b_256_state;
#endif
};
@@ -429,13 +429,13 @@ blake2_update_unlocked(Blake2Object *self, uint8_t *buf, Py_ssize_t len)
switch (self->impl) {
// blake2b_256_state and blake2s_128_state must be if'd since
// otherwise this results in an unresolved symbol at link-time.
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
case Blake2b_256:
HACL_UPDATE(Hacl_Hash_Blake2b_Simd256_update,
self->blake2b_256_state, buf, len);
return;
#endif
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
case Blake2s_128:
HACL_UPDATE(Hacl_Hash_Blake2s_Simd128_update,
self->blake2s_128_state, buf, len);
@@ -555,12 +555,12 @@ py_blake2_new(PyTypeObject *type, PyObject *data, int digest_size,
// Ensure that the states are NULL-initialized in case of an error.
// See: py_blake2_clear() for more details.
switch (self->impl) {
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
case Blake2b_256:
self->blake2b_256_state = NULL;
break;
#endif
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
case Blake2s_128:
self->blake2s_128_state = NULL;
break;
@@ -623,12 +623,12 @@ py_blake2_new(PyTypeObject *type, PyObject *data, int digest_size,
} while (0)
switch (self->impl) {
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
case Blake2b_256:
BLAKE2_MALLOC(Blake2b_Simd256, self->blake2b_256_state);
break;
#endif
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
case Blake2s_128:
BLAKE2_MALLOC(Blake2s_Simd128, self->blake2s_128_state);
break;
@@ -756,12 +756,12 @@ blake2_blake2b_copy_unlocked(Blake2Object *self, Blake2Object *cpy)
} while (0)
switch (self->impl) {
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
case Blake2b_256:
BLAKE2_COPY(Blake2b_Simd256, blake2b_256_state);
break;
#endif
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
case Blake2s_128:
BLAKE2_COPY(Blake2s_Simd128, blake2s_128_state);
break;
@@ -840,12 +840,12 @@ static uint8_t
blake2_blake2b_compute_digest(Blake2Object *self, uint8_t *digest)
{
switch (self->impl) {
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
case Blake2b_256:
return Hacl_Hash_Blake2b_Simd256_digest(
self->blake2b_256_state, digest);
#endif
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
case Blake2s_128:
return Hacl_Hash_Blake2s_Simd128_digest(
self->blake2s_128_state, digest);
@@ -923,11 +923,11 @@ static Hacl_Hash_Blake2b_index
hacl_get_blake2_info(Blake2Object *self)
{
switch (self->impl) {
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
case Blake2b_256:
return Hacl_Hash_Blake2b_Simd256_info(self->blake2b_256_state);
#endif
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
case Blake2s_128:
return Hacl_Hash_Blake2s_Simd128_info(self->blake2s_128_state);
#endif
@@ -975,12 +975,12 @@ py_blake2_clear(PyObject *op)
} while (0)
switch (self->impl) {
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
case Blake2b_256:
BLAKE2_FREE(Blake2b_Simd256, self->blake2b_256_state);
break;
#endif
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
case Blake2s_128:
BLAKE2_FREE(Blake2s_Simd128, self->blake2s_128_state);
break;
diff --git a/Modules/clinic/_remote_debugging_module.c.h b/Modules/clinic/_remote_debugging_module.c.h
index 5c313a2d664..e80b24b54c0 100644
--- a/Modules/clinic/_remote_debugging_module.c.h
+++ b/Modules/clinic/_remote_debugging_module.c.h
@@ -10,7 +10,8 @@ preserve
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
PyDoc_STRVAR(_remote_debugging_RemoteUnwinder___init____doc__,
-"RemoteUnwinder(pid, *, all_threads=False, debug=False)\n"
+"RemoteUnwinder(pid, *, all_threads=False, only_active_thread=False,\n"
+" debug=False)\n"
"--\n"
"\n"
"Initialize a new RemoteUnwinder object for debugging a remote Python process.\n"
@@ -19,6 +20,8 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder___init____doc__,
" pid: Process ID of the target Python process to debug\n"
" all_threads: If True, initialize state for all threads in the process.\n"
" If False, only initialize for the main thread.\n"
+" only_active_thread: If True, only sample the thread holding the GIL.\n"
+" Cannot be used together with all_threads=True.\n"
" debug: If True, chain exceptions to explain the sequence of events that\n"
" lead to the exception.\n"
"\n"
@@ -28,11 +31,13 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder___init____doc__,
"Raises:\n"
" PermissionError: If access to the target process is denied\n"
" OSError: If unable to attach to the target process or access its memory\n"
-" RuntimeError: If unable to read debug information from the target process");
+" RuntimeError: If unable to read debug information from the target process\n"
+" ValueError: If both all_threads and only_active_thread are True");
static int
_remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self,
int pid, int all_threads,
+ int only_active_thread,
int debug);
static int
@@ -41,7 +46,7 @@ _remote_debugging_RemoteUnwinder___init__(PyObject *self, PyObject *args, PyObje
int return_value = -1;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 3
+ #define NUM_KEYWORDS 4
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -50,7 +55,7 @@ _remote_debugging_RemoteUnwinder___init__(PyObject *self, PyObject *args, PyObje
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(pid), &_Py_ID(all_threads), &_Py_ID(debug), },
+ .ob_item = { &_Py_ID(pid), &_Py_ID(all_threads), &_Py_ID(only_active_thread), &_Py_ID(debug), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -59,19 +64,20 @@ _remote_debugging_RemoteUnwinder___init__(PyObject *self, PyObject *args, PyObje
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"pid", "all_threads", "debug", NULL};
+ static const char * const _keywords[] = {"pid", "all_threads", "only_active_thread", "debug", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "RemoteUnwinder",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[4];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
int pid;
int all_threads = 0;
+ int only_active_thread = 0;
int debug = 0;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser,
@@ -95,12 +101,21 @@ _remote_debugging_RemoteUnwinder___init__(PyObject *self, PyObject *args, PyObje
goto skip_optional_kwonly;
}
}
- debug = PyObject_IsTrue(fastargs[2]);
+ if (fastargs[2]) {
+ only_active_thread = PyObject_IsTrue(fastargs[2]);
+ if (only_active_thread < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
+ }
+ debug = PyObject_IsTrue(fastargs[3]);
if (debug < 0) {
goto exit;
}
skip_optional_kwonly:
- return_value = _remote_debugging_RemoteUnwinder___init___impl((RemoteUnwinderObject *)self, pid, all_threads, debug);
+ return_value = _remote_debugging_RemoteUnwinder___init___impl((RemoteUnwinderObject *)self, pid, all_threads, only_active_thread, debug);
exit:
return return_value;
@@ -110,13 +125,18 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_stack_trace__doc__,
"get_stack_trace($self, /)\n"
"--\n"
"\n"
-"Returns a list of stack traces for all threads in the target process.\n"
+"Returns a list of stack traces for threads in the target process.\n"
"\n"
"Each element in the returned list is a tuple of (thread_id, frame_list), where:\n"
"- thread_id is the OS thread identifier\n"
"- frame_list is a list of tuples (function_name, filename, line_number) representing\n"
" the Python stack frames for that thread, ordered from most recent to oldest\n"
"\n"
+"The threads returned depend on the initialization parameters:\n"
+"- If only_active_thread was True: returns only the thread holding the GIL\n"
+"- If all_threads was True: returns all threads\n"
+"- Otherwise: returns only the main thread\n"
+"\n"
"Example:\n"
" [\n"
" (1234, [\n"
@@ -253,4 +273,4 @@ _remote_debugging_RemoteUnwinder_get_async_stack_trace(PyObject *self, PyObject
return return_value;
}
-/*[clinic end generated code: output=774ec34aa653402d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=a37ab223d5081b16 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h
index fbb012fb6dd..a443c48faaa 100644
--- a/Modules/clinic/mathmodule.c.h
+++ b/Modules/clinic/mathmodule.c.h
@@ -84,6 +84,40 @@ PyDoc_STRVAR(math_floor__doc__,
#define MATH_FLOOR_METHODDEF \
{"floor", (PyCFunction)math_floor, METH_O, math_floor__doc__},
+PyDoc_STRVAR(math_signbit__doc__,
+"signbit($module, x, /)\n"
+"--\n"
+"\n"
+"Return True if the sign of x is negative and False otherwise.");
+
+#define MATH_SIGNBIT_METHODDEF \
+ {"signbit", (PyCFunction)math_signbit, METH_O, math_signbit__doc__},
+
+static PyObject *
+math_signbit_impl(PyObject *module, double x);
+
+static PyObject *
+math_signbit(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ double x;
+
+ if (PyFloat_CheckExact(arg)) {
+ x = PyFloat_AS_DOUBLE(arg);
+ }
+ else
+ {
+ x = PyFloat_AsDouble(arg);
+ if (x == -1.0 && PyErr_Occurred()) {
+ goto exit;
+ }
+ }
+ return_value = math_signbit_impl(module, x);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(math_fsum__doc__,
"fsum($module, seq, /)\n"
"--\n"
@@ -1178,4 +1212,4 @@ math_ulp(PyObject *module, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=44bba3a0a052a364 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4e3fa94d026f027b input=a9049054013a1b77]*/
diff --git a/Modules/getpath.py b/Modules/getpath.py
index be2210345af..b89d7427e3f 100644
--- a/Modules/getpath.py
+++ b/Modules/getpath.py
@@ -364,10 +364,9 @@ if not py_setpath:
venv_prefix = None
pyvenvcfg = []
- # Search for the 'home' key in pyvenv.cfg. Currently, we don't consider the
- # presence of a pyvenv.cfg file without a 'home' key to signify the
- # existence of a virtual environment — we quietly ignore them.
- # XXX: If we don't find a 'home' key, we don't look for another pyvenv.cfg!
+ # Search for the 'home' key in pyvenv.cfg. If a home key isn't found,
+ # then it means a venv is active and home is based on the venv's
+ # executable (if its a symlink, home is where the symlink points).
for line in pyvenvcfg:
key, had_equ, value = line.partition('=')
if had_equ and key.strip().lower() == 'home':
@@ -412,10 +411,8 @@ if not py_setpath:
if isfile(candidate):
base_executable = candidate
break
+ # home key found; stop iterating over lines
break
- else:
- # We didn't find a 'home' key in pyvenv.cfg (no break), reset venv_prefix.
- venv_prefix = None
# ******************************************************************************
diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c
index e7a5ccbb19b..95e400231bb 100644
--- a/Modules/hmacmodule.c
+++ b/Modules/hmacmodule.c
@@ -31,14 +31,15 @@
#endif
#if defined(__APPLE__) && defined(__arm64__)
-# undef HACL_CAN_COMPILE_SIMD128
-# undef HACL_CAN_COMPILE_SIMD256
+# undef _Py_HACL_CAN_COMPILE_VEC128
+# undef _Py_HACL_CAN_COMPILE_VEC256
#endif
-// Small mismatch between the variable names Python defines as part of configure
-// at the ones HACL* expects to be set in order to enable those headers.
-#define HACL_CAN_COMPILE_VEC128 HACL_CAN_COMPILE_SIMD128
-#define HACL_CAN_COMPILE_VEC256 HACL_CAN_COMPILE_SIMD256
+// HACL* expects HACL_CAN_COMPILE_VEC* macros to be set in order to enable
+// the corresponding SIMD instructions so we need to "forward" the values
+// we just deduced above.
+#define HACL_CAN_COMPILE_VEC128 _Py_HACL_CAN_COMPILE_VEC128
+#define HACL_CAN_COMPILE_VEC256 _Py_HACL_CAN_COMPILE_VEC256
#include "_hacl/Hacl_HMAC.h"
#include "_hacl/Hacl_Streaming_HMAC.h" // Hacl_Agile_Hash_* identifiers
@@ -361,7 +362,7 @@ narrow_hmac_hash_kind(hmacmodule_state *state, HMAC_Hash_Kind kind)
{
switch (kind) {
case Py_hmac_kind_hmac_blake2s_32: {
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
if (state->can_run_simd128) {
return Py_hmac_kind_hmac_vectorized_blake2s_32;
}
@@ -369,7 +370,7 @@ narrow_hmac_hash_kind(hmacmodule_state *state, HMAC_Hash_Kind kind)
return kind;
}
case Py_hmac_kind_hmac_blake2b_32: {
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
if (state->can_run_simd256) {
return Py_hmac_kind_hmac_vectorized_blake2b_32;
}
@@ -1601,7 +1602,7 @@ hmacmodule_init_cpu_features(hmacmodule_state *state)
#undef ECX_SSE3
#undef EBX_AVX2
-#if HACL_CAN_COMPILE_SIMD128
+#if _Py_HACL_CAN_COMPILE_VEC128
// TODO(picnixz): use py_cpuid_features (gh-125022) to improve detection
state->can_run_simd128 = sse && sse2 && sse3 && sse41 && sse42 && cmov;
#else
@@ -1611,7 +1612,7 @@ hmacmodule_init_cpu_features(hmacmodule_state *state)
state->can_run_simd128 = false;
#endif
-#if HACL_CAN_COMPILE_SIMD256
+#if _Py_HACL_CAN_COMPILE_VEC256
// TODO(picnixz): use py_cpuid_features (gh-125022) to improve detection
state->can_run_simd256 = state->can_run_simd128 && avx && avx2;
#else
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 2003546ce84..cc1a5580015 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -1880,8 +1880,8 @@ chain_traverse(PyObject *op, visitproc visit, void *arg)
return 0;
}
-static PyObject *
-chain_next(PyObject *op)
+static inline PyObject *
+chain_next_lock_held(PyObject *op)
{
chainobject *lz = chainobject_CAST(op);
PyObject *item;
@@ -1919,6 +1919,16 @@ chain_next(PyObject *op)
return NULL;
}
+static PyObject *
+chain_next(PyObject *op)
+{
+ PyObject *result;
+ Py_BEGIN_CRITICAL_SECTION(op);
+ result = chain_next_lock_held(op);
+ Py_END_CRITICAL_SECTION()
+ return result;
+}
+
PyDoc_STRVAR(chain_doc,
"chain(*iterables)\n\
--\n\
@@ -2086,7 +2096,7 @@ product_traverse(PyObject *op, visitproc visit, void *arg)
}
static PyObject *
-product_next(PyObject *op)
+product_next_lock_held(PyObject *op)
{
productobject *lz = productobject_CAST(op);
PyObject *pool;
@@ -2172,6 +2182,16 @@ empty:
return NULL;
}
+static PyObject *
+product_next(PyObject *op)
+{
+ PyObject *result;
+ Py_BEGIN_CRITICAL_SECTION(op);
+ result = product_next_lock_held(op);
+ Py_END_CRITICAL_SECTION()
+ return result;
+}
+
static PyMethodDef product_methods[] = {
{"__sizeof__", product_sizeof, METH_NOARGS, sizeof_doc},
{NULL, NULL} /* sentinel */
@@ -2319,7 +2339,7 @@ combinations_traverse(PyObject *op, visitproc visit, void *arg)
}
static PyObject *
-combinations_next(PyObject *op)
+combinations_next_lock_held(PyObject *op)
{
combinationsobject *co = combinationsobject_CAST(op);
PyObject *elem;
@@ -2404,6 +2424,16 @@ empty:
return NULL;
}
+static PyObject *
+combinations_next(PyObject *op)
+{
+ PyObject *result;
+ Py_BEGIN_CRITICAL_SECTION(op);
+ result = combinations_next_lock_held(op);
+ Py_END_CRITICAL_SECTION()
+ return result;
+}
+
static PyMethodDef combinations_methods[] = {
{"__sizeof__", combinations_sizeof, METH_NOARGS, sizeof_doc},
{NULL, NULL} /* sentinel */
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 1837de4735c..033de0b2907 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -1233,6 +1233,23 @@ FUNC2(remainder, m_remainder,
"Return x - n*y where n*y is the closest integer multiple of y.\n"
"In the case where x is exactly halfway between two multiples of\n"
"y, the nearest even value of n is used. The result is always exact.")
+
+/*[clinic input]
+math.signbit
+
+ x: double
+ /
+
+Return True if the sign of x is negative and False otherwise.
+[clinic start generated code]*/
+
+static PyObject *
+math_signbit_impl(PyObject *module, double x)
+/*[clinic end generated code: output=20c5f20156a9b871 input=3d3493fbcb5bdb3e]*/
+{
+ return PyBool_FromLong(signbit(x));
+}
+
FUNC1D(sin, sin, 0,
"sin($module, x, /)\n--\n\n"
"Return the sine of x (measured in radians).",
@@ -4199,6 +4216,7 @@ static PyMethodDef math_methods[] = {
MATH_POW_METHODDEF
MATH_RADIANS_METHODDEF
{"remainder", _PyCFunction_CAST(math_remainder), METH_FASTCALL, math_remainder_doc},
+ MATH_SIGNBIT_METHODDEF
{"sin", math_sin, METH_O, math_sin_doc},
{"sinh", math_sinh, METH_O, math_sinh_doc},
{"sqrt", math_sqrt, METH_O, math_sqrt_doc},
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 7c4eb05488e..142ff1a2131 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -25,6 +25,7 @@
#include <Python.h>
#include "pycore_bytesobject.h" // _PyBytes_Find()
#include "pycore_fileutils.h" // _Py_stat_struct
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include <stddef.h> // offsetof()
#ifndef MS_WINDOWS
@@ -163,8 +164,7 @@ mmap_object_dealloc(PyObject *op)
Py_END_ALLOW_THREADS
#endif /* UNIX */
- if (m_obj->weakreflist != NULL)
- PyObject_ClearWeakRefs(op);
+ FT_CLEAR_WEAKREFS(op, m_obj->weakreflist);
tp->tp_free(m_obj);
Py_DECREF(tp);
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index fa153d86543..c449dd848d1 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -98,7 +98,11 @@ typedef struct {
#define CHARACTER_DATA_BUFFER_SIZE 8192
-typedef const void *xmlhandler;
+// A generic function type for storage.
+// To avoid undefined behaviors, a handler must be cast to the correct
+// function type before it's called; see SETTER_WRAPPER below.
+typedef void (*xmlhandler)(void);
+
typedef void (*xmlhandlersetter)(XML_Parser self, xmlhandler handler);
struct HandlerInfo {
@@ -110,9 +114,7 @@ struct HandlerInfo {
static struct HandlerInfo handler_info[64];
-// gh-111178: Use _Py_NO_SANITIZE_UNDEFINED, rather than using the exact
-// handler API for each handler.
-static inline void _Py_NO_SANITIZE_UNDEFINED
+static inline void
CALL_XML_HANDLER_SETTER(const struct HandlerInfo *handler_info,
XML_Parser xml_parser, xmlhandler xml_handler)
{
@@ -1365,7 +1367,7 @@ xmlparse_handler_setter(PyObject *op, PyObject *v, void *closure)
elaborate system of handlers and state could remove the
C handler more effectively. */
if (handlernum == CharacterData && self->in_callback) {
- c_handler = noop_character_data_handler;
+ c_handler = (xmlhandler)noop_character_data_handler;
}
v = NULL;
}
@@ -2222,13 +2224,84 @@ clear_handlers(xmlparseobject *self, int initial)
}
}
+/* To avoid undefined behaviors, a function must be *called* via a function
+ * pointer of the correct type.
+ * So, for each `XML_Set*` function, we define a wrapper that calls `XML_Set*`
+ * with its argument cast to the appropriate type.
+ */
+
+typedef void (*parser_only)(void *);
+typedef int (*not_standalone)(void *);
+typedef void (*parser_and_data)(void *, const XML_Char *);
+typedef void (*parser_and_data_and_int)(void *, const XML_Char *, int);
+typedef void (*parser_and_data_and_data)(
+ void *, const XML_Char *, const XML_Char *);
+typedef void (*start_element)(void *, const XML_Char *, const XML_Char **);
+typedef void (*element_decl)(void *, const XML_Char *, XML_Content *);
+typedef void (*xml_decl)(
+ void *, const XML_Char *, const XML_Char *, int);
+typedef void (*start_doctype_decl)(
+ void *, const XML_Char *, const XML_Char *, const XML_Char *, int);
+typedef void (*notation_decl)(
+ void *,
+ const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
+typedef void (*attlist_decl)(
+ void *,
+ const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *,
+ int);
+typedef void (*unparsed_entity_decl)(
+ void *,
+ const XML_Char *, const XML_Char *,
+ const XML_Char *, const XML_Char *, const XML_Char *);
+typedef void (*entity_decl)(
+ void *,
+ const XML_Char *, int,
+ const XML_Char *, int,
+ const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
+typedef int (*external_entity_ref)(
+ XML_Parser,
+ const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
+
+#define SETTER_WRAPPER(NAME, TYPE) \
+ static inline void \
+ pyexpat_Set ## NAME (XML_Parser parser, xmlhandler handler) \
+ { \
+ (void)XML_Set ## NAME (parser, (TYPE)handler); \
+ }
+
+SETTER_WRAPPER(StartElementHandler, start_element)
+SETTER_WRAPPER(EndElementHandler, parser_and_data)
+SETTER_WRAPPER(ProcessingInstructionHandler, parser_and_data_and_data)
+SETTER_WRAPPER(CharacterDataHandler, parser_and_data_and_int)
+SETTER_WRAPPER(UnparsedEntityDeclHandler, unparsed_entity_decl)
+SETTER_WRAPPER(NotationDeclHandler, notation_decl)
+SETTER_WRAPPER(StartNamespaceDeclHandler, parser_and_data_and_data)
+SETTER_WRAPPER(EndNamespaceDeclHandler, parser_and_data)
+SETTER_WRAPPER(CommentHandler, parser_and_data)
+SETTER_WRAPPER(StartCdataSectionHandler, parser_only)
+SETTER_WRAPPER(EndCdataSectionHandler, parser_only)
+SETTER_WRAPPER(DefaultHandler, parser_and_data_and_int)
+SETTER_WRAPPER(DefaultHandlerExpand, parser_and_data_and_int)
+SETTER_WRAPPER(NotStandaloneHandler, not_standalone)
+SETTER_WRAPPER(ExternalEntityRefHandler, external_entity_ref)
+SETTER_WRAPPER(StartDoctypeDeclHandler, start_doctype_decl)
+SETTER_WRAPPER(EndDoctypeDeclHandler, parser_only)
+SETTER_WRAPPER(EntityDeclHandler, entity_decl)
+SETTER_WRAPPER(XmlDeclHandler, xml_decl)
+SETTER_WRAPPER(ElementDeclHandler, element_decl)
+SETTER_WRAPPER(AttlistDeclHandler, attlist_decl)
+#if XML_COMBINED_VERSION >= 19504
+SETTER_WRAPPER(SkippedEntityHandler, parser_and_data_and_int)
+#endif
+#undef SETTER_WRAPPER
+
static struct HandlerInfo handler_info[] = {
// The cast to `xmlhandlersetter` is needed as the signature of XML
// handler functions is not compatible with `xmlhandlersetter` since
// their second parameter is narrower than a `const void *`.
#define HANDLER_INFO(name) \
- {#name, (xmlhandlersetter)XML_Set##name, my_##name},
+ {#name, (xmlhandlersetter)pyexpat_Set##name, (xmlhandler)my_##name},
HANDLER_INFO(StartElementHandler)
HANDLER_INFO(EndElementHandler)