Skip to content

Commit 7bfde50

Browse files
committed
Merge branch 'main' of github.com:python/cpython into remove-__package__
2 parents d625711 + 69f54ce commit 7bfde50

File tree

11 files changed

+84
-25
lines changed

11 files changed

+84
-25
lines changed

Doc/library/xmlrpc.client.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ remote server into a single request [#]_.
472472

473473
Create an object used to boxcar method calls. *server* is the eventual target of
474474
the call. Calls can be made to the result object, but they will immediately
475-
return ``None``, and only store the call name and parameters in the
475+
return ``None``, and only store the call name and arguments in the
476476
:class:`MultiCall` object. Calling the object itself causes all stored calls to
477477
be transmitted as a single ``system.multicall`` request. The result of this call
478478
is a :term:`generator`; iterating over this generator yields the individual

Include/cpython/object.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,6 @@ PyAPI_FUNC(void) _Py_NO_RETURN _PyObject_AssertFailed(
436436
PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyThreadState *tstate, PyObject *op);
437437
PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(PyThreadState *tstate);
438438

439-
PyAPI_FUNC(int) _Py_ReachedRecursionLimitWithMargin(PyThreadState *tstate, int margin_count);
440-
441439
/* For backwards compatibility with the old trashcan mechanism */
442440
#define Py_TRASHCAN_BEGIN(op, dealloc)
443441
#define Py_TRASHCAN_END

Include/internal/pycore_ceval.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,11 @@ static inline int _Py_ReachedRecursionLimit(PyThreadState *tstate) {
263263
#endif
264264
}
265265

266+
// Export for test_peg_generator
267+
PyAPI_FUNC(int) _Py_ReachedRecursionLimitWithMargin(
268+
PyThreadState *tstate,
269+
int margin_count);
270+
266271
static inline void _Py_LeaveRecursiveCall(void) {
267272
}
268273

Include/internal/pycore_pymem.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,27 @@ static inline int _PyMem_IsPtrFreed(const void *ptr)
7070
#endif
7171
}
7272

73+
// Similar to _PyMem_IsPtrFreed() but expects an 'unsigned long' instead of a
74+
// pointer.
75+
static inline int _PyMem_IsULongFreed(unsigned long value)
76+
{
77+
#if SIZEOF_LONG == 8
78+
return (value == 0
79+
|| value == (unsigned long)0xCDCDCDCDCDCDCDCD
80+
|| value == (unsigned long)0xDDDDDDDDDDDDDDDD
81+
|| value == (unsigned long)0xFDFDFDFDFDFDFDFD
82+
|| value == (unsigned long)0xFFFFFFFFFFFFFFFF);
83+
#elif SIZEOF_LONG == 4
84+
return (value == 0
85+
|| value == (unsigned long)0xCDCDCDCD
86+
|| value == (unsigned long)0xDDDDDDDD
87+
|| value == (unsigned long)0xFDFDFDFD
88+
|| value == (unsigned long)0xFFFFFFFF);
89+
#else
90+
# error "unknown long size"
91+
#endif
92+
}
93+
7394
extern int _PyMem_GetAllocatorName(
7495
const char *name,
7596
PyMemAllocatorName *allocator);

Include/internal/pycore_tracemalloc.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ struct _PyTraceMalloc_Config {
3030
};
3131

3232

33-
/* Pack the frame_t structure to reduce the memory footprint on 64-bit
34-
architectures: 12 bytes instead of 16. */
33+
/* Pack the tracemalloc_frame and tracemalloc_traceback structures to reduce
34+
the memory footprint on 64-bit architectures: 12 bytes instead of 16. */
3535
#if defined(_MSC_VER)
3636
#pragma pack(push, 4)
3737
#endif
@@ -46,18 +46,22 @@ tracemalloc_frame {
4646
PyObject *filename;
4747
unsigned int lineno;
4848
};
49-
#ifdef _MSC_VER
50-
#pragma pack(pop)
51-
#endif
5249

53-
struct tracemalloc_traceback {
50+
struct
51+
#ifdef __GNUC__
52+
__attribute__((packed))
53+
#endif
54+
tracemalloc_traceback {
5455
Py_uhash_t hash;
5556
/* Number of frames stored */
5657
uint16_t nframe;
5758
/* Total number of frames the traceback had */
5859
uint16_t total_nframe;
59-
struct tracemalloc_frame frames[1];
60+
struct tracemalloc_frame frames[];
6061
};
62+
#ifdef _MSC_VER
63+
#pragma pack(pop)
64+
#endif
6165

6266

6367
struct _tracemalloc_runtime_state {
@@ -95,7 +99,7 @@ struct _tracemalloc_runtime_state {
9599
Protected by TABLES_LOCK(). */
96100
_Py_hashtable_t *domains;
97101

98-
struct tracemalloc_traceback empty_traceback;
102+
struct tracemalloc_traceback *empty_traceback;
99103

100104
Py_tss_t reentrant_key;
101105
};

Lib/test/test_sysconfig.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
)
2121
from test.support.import_helper import import_module
2222
from test.support.os_helper import (TESTFN, unlink, skip_unless_symlink,
23-
change_cwd)
23+
change_cwd, EnvironmentVarGuard)
2424
from test.support.venv import VirtualEnvironmentMixin
2525

2626
import sysconfig
@@ -807,7 +807,9 @@ def test_parse_makefile_renamed_vars(self):
807807
print("PY_LDFLAGS=-lm", file=makefile)
808808
print("var2=$(LDFLAGS)", file=makefile)
809809
print("var3=$(CPPFLAGS)", file=makefile)
810-
vars = _parse_makefile(TESTFN)
810+
with EnvironmentVarGuard() as env:
811+
env.clear()
812+
vars = _parse_makefile(TESTFN)
811813
self.assertEqual(vars, {
812814
'var1': '-Wall',
813815
'CFLAGS': '-Wall',
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make ``test_sysconfig.test_parse_makefile_renamed_vars`` less fragile by
2+
clearing the environment variables before parsing the Makefile.

Parser/parser.c

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/traceback.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,9 @@ tstate_is_freed(PyThreadState *tstate)
10941094
if (_PyMem_IsPtrFreed(tstate->interp)) {
10951095
return 1;
10961096
}
1097+
if (_PyMem_IsULongFreed(tstate->thread_id)) {
1098+
return 1;
1099+
}
10971100
return 0;
10981101
}
10991102

@@ -1113,7 +1116,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
11131116
}
11141117

11151118
if (tstate_is_freed(tstate)) {
1116-
PUTS(fd, " <tstate is freed>\n");
1119+
PUTS(fd, " <freed thread state>\n");
11171120
return;
11181121
}
11191122

@@ -1138,12 +1141,16 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
11381141
PUTS(fd, " <freed frame>\n");
11391142
break;
11401143
}
1144+
// Read frame->previous early since memory can be freed during
1145+
// dump_frame()
1146+
_PyInterpreterFrame *previous = frame->previous;
1147+
11411148
if (dump_frame(fd, frame) < 0) {
11421149
PUTS(fd, " <invalid frame>\n");
11431150
break;
11441151
}
11451152

1146-
frame = frame->previous;
1153+
frame = previous;
11471154
if (frame == NULL) {
11481155
break;
11491156
}
@@ -1240,7 +1247,9 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
12401247
tstate->thread_id,
12411248
sizeof(unsigned long) * 2);
12421249

1243-
write_thread_name(fd, tstate);
1250+
if (!_PyMem_IsULongFreed(tstate->thread_id)) {
1251+
write_thread_name(fd, tstate);
1252+
}
12441253

12451254
PUTS(fd, " (most recent call first):\n");
12461255
}
@@ -1298,7 +1307,6 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
12981307
return "unable to get the thread head state";
12991308

13001309
/* Dump the traceback of each thread */
1301-
tstate = PyInterpreterState_ThreadHead(interp);
13021310
unsigned int nthreads = 0;
13031311
_Py_BEGIN_SUPPRESS_IPH
13041312
do
@@ -1309,11 +1317,18 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
13091317
PUTS(fd, "...\n");
13101318
break;
13111319
}
1320+
1321+
if (tstate_is_freed(tstate)) {
1322+
PUTS(fd, "<freed thread state>\n");
1323+
break;
1324+
}
1325+
13121326
write_thread_id(fd, tstate, tstate == current_tstate);
13131327
if (tstate == current_tstate && tstate->interp->gc.collecting) {
13141328
PUTS(fd, " Garbage-collecting\n");
13151329
}
13161330
dump_traceback(fd, tstate, 0);
1331+
13171332
tstate = PyThreadState_Next(tstate);
13181333
nthreads++;
13191334
} while (tstate != NULL);

Python/tracemalloc.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ typedef struct tracemalloc_frame frame_t;
4646
typedef struct tracemalloc_traceback traceback_t;
4747

4848
#define TRACEBACK_SIZE(NFRAME) \
49-
(sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
49+
(sizeof(traceback_t) + sizeof(frame_t) * (NFRAME))
5050

5151
static const int MAX_NFRAME = UINT16_MAX;
5252

@@ -329,8 +329,9 @@ traceback_new(void)
329329
traceback->nframe = 0;
330330
traceback->total_nframe = 0;
331331
traceback_get_frames(traceback);
332-
if (traceback->nframe == 0)
333-
return &tracemalloc_empty_traceback;
332+
if (traceback->nframe == 0) {
333+
return tracemalloc_empty_traceback;
334+
}
334335
traceback->hash = traceback_hash(traceback);
335336

336337
/* intern the traceback */
@@ -754,12 +755,18 @@ _PyTraceMalloc_Init(void)
754755
return _PyStatus_NO_MEMORY();
755756
}
756757

757-
tracemalloc_empty_traceback.nframe = 1;
758-
tracemalloc_empty_traceback.total_nframe = 1;
758+
assert(tracemalloc_empty_traceback == NULL);
759+
tracemalloc_empty_traceback = raw_malloc(TRACEBACK_SIZE(1));
760+
if (tracemalloc_empty_traceback == NULL) {
761+
return _PyStatus_NO_MEMORY();
762+
}
763+
764+
tracemalloc_empty_traceback->nframe = 1;
765+
tracemalloc_empty_traceback->total_nframe = 1;
759766
/* borrowed reference */
760-
tracemalloc_empty_traceback.frames[0].filename = &_Py_STR(anon_unknown);
761-
tracemalloc_empty_traceback.frames[0].lineno = 0;
762-
tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
767+
tracemalloc_empty_traceback->frames[0].filename = &_Py_STR(anon_unknown);
768+
tracemalloc_empty_traceback->frames[0].lineno = 0;
769+
tracemalloc_empty_traceback->hash = traceback_hash(tracemalloc_empty_traceback);
763770

764771
tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
765772
return _PyStatus_OK();
@@ -782,6 +789,9 @@ tracemalloc_deinit(void)
782789
_Py_hashtable_destroy(tracemalloc_filenames);
783790

784791
PyThread_tss_delete(&tracemalloc_reentrant_key);
792+
793+
raw_free(tracemalloc_empty_traceback);
794+
tracemalloc_empty_traceback = NULL;
785795
}
786796

787797

0 commit comments

Comments
 (0)