Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions Doc/library/warnings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -480,14 +480,21 @@ Available Functions
.. function:: warn_explicit(message, category, filename, lineno, module=None, registry=None, module_globals=None, source=None)

This is a low-level interface to the functionality of :func:`warn`, passing in
explicitly the message, category, filename and line number, and optionally the
module name and the registry (which should be the ``__warningregistry__``
dictionary of the module). The module name defaults to the filename with
``.py`` stripped; if no registry is passed, the warning is never suppressed.
explicitly the message, category, filename and line number, and optionally
other arguments.
*message* must be a string and *category* a subclass of :exc:`Warning` or
*message* may be a :exc:`Warning` instance, in which case *category* will be
ignored.

*module*, if supplied, should be the module name.
If no module is passed, the filename with ``.py`` stripped is used.

*registry*, if supplied, should be the ``__warningregistry__`` dictionary
of the module.
If no registry is passed, each warning is treated as the first occurrence,
that is, filter actions ``"default"``, ``"module"`` and ``"once"`` are
handled as ``"always"``.

*module_globals*, if supplied, should be the global namespace in use by the code
for which the warning is issued. (This argument is used to support displaying
source for modules found in zipfiles or other non-filesystem import
Expand Down
6 changes: 0 additions & 6 deletions Include/internal/pycore_interp_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -769,12 +769,6 @@ struct _is {
* and should be placed at the beginning. */
struct _ceval_state ceval;

/* This structure is carefully allocated so that it's correctly aligned
* to avoid undefined behaviors during LOAD and STORE. The '_malloced'
* field stores the allocated pointer address that will later be freed.
*/
void *_malloced;

PyInterpreterState *next;

int64_t id;
Expand Down
5 changes: 4 additions & 1 deletion Lib/asyncio/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ def run(self):
if CAN_USE_PYREPL:
theme = get_theme().syntax
ps1 = f"{theme.prompt}{ps1}{theme.reset}"
console.write(f"{ps1}import asyncio\n")
import_line = f'{theme.keyword}import{theme.reset} asyncio'
else:
import_line = "import asyncio"
console.write(f"{ps1}{import_line}\n")

if CAN_USE_PYREPL:
from _pyrepl.simple_interact import (
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -1776,6 +1776,7 @@ def task():
self.assertEqual(os.read(r_interp, 1), DONE)

@cpython_only
@support.skip_if_sanitizer(thread=True, memory=True)
def test_daemon_threads_fatal_error(self):
import_module("_testcapi")
subinterp_code = f"""if 1:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix memory leak in sub-interpreter creation.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix data race between interpreter_clear() and take_gil() on eval_breaker
during finalization with daemon threads.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Colorize the default import statement ``import asyncio`` in asyncio REPL.
22 changes: 13 additions & 9 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,16 +457,19 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime)
static PyInterpreterState *
alloc_interpreter(void)
{
// Aligned allocation for PyInterpreterState.
// the first word of the memory block is used to store
// the original pointer to be used later to free the memory.
size_t alignment = _Alignof(PyInterpreterState);
size_t allocsize = sizeof(PyInterpreterState) + alignment - 1;
size_t allocsize = sizeof(PyInterpreterState) + sizeof(void *) + alignment - 1;
void *mem = PyMem_RawCalloc(1, allocsize);
if (mem == NULL) {
return NULL;
}
PyInterpreterState *interp = _Py_ALIGN_UP(mem, alignment);
assert(_Py_IS_ALIGNED(interp, alignment));
interp->_malloced = mem;
return interp;
void *ptr = _Py_ALIGN_UP((char *)mem + sizeof(void *), alignment);
((void **)ptr)[-1] = mem;
assert(_Py_IS_ALIGNED(ptr, alignment));
return ptr;
}

static void
Expand All @@ -481,7 +484,7 @@ free_interpreter(PyInterpreterState *interp)
interp->obmalloc = NULL;
}
assert(_Py_IS_ALIGNED(interp, _Alignof(PyInterpreterState)));
PyMem_RawFree(interp->_malloced);
PyMem_RawFree(((void **)interp)[-1]);
}
}

Expand Down Expand Up @@ -763,10 +766,11 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)

Py_CLEAR(interp->audit_hooks);

// At this time, all the threads should be cleared so we don't need atomic
// operations for instrumentation_version or eval_breaker.
// gh-140257: Threads have already been cleared, but daemon threads may
// still access eval_breaker atomically via take_gil() right before they
// hang. Use an atomic store to prevent data races during finalization.
interp->ceval.instrumentation_version = 0;
tstate->eval_breaker = 0;
_Py_atomic_store_uintptr(&tstate->eval_breaker, 0);

for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) {
interp->monitors.tools[i] = 0;
Expand Down
Loading