Skip to content

Commit 59bc36a

Browse files
gh-84436: Immortalize in _PyStructSequence_InitBuiltinWithFlags() (gh-104054)
This also does some cleanup.
1 parent d448fcb commit 59bc36a

File tree

8 files changed

+74
-59
lines changed

8 files changed

+74
-59
lines changed

Include/internal/pycore_structseq.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ PyAPI_FUNC(PyTypeObject *) _PyStructSequence_NewType(
1515
PyStructSequence_Desc *desc,
1616
unsigned long tp_flags);
1717

18-
PyAPI_FUNC(int) _PyStructSequence_InitBuiltinWithFlags(
18+
extern int _PyStructSequence_InitBuiltinWithFlags(
1919
PyTypeObject *type,
2020
PyStructSequence_Desc *desc,
2121
unsigned long tp_flags);
@@ -27,7 +27,7 @@ _PyStructSequence_InitBuiltin(PyTypeObject *type,
2727
return _PyStructSequence_InitBuiltinWithFlags(type, desc, 0);
2828
}
2929

30-
extern void _PyStructSequence_FiniType(PyTypeObject *type);
30+
extern void _PyStructSequence_FiniBuiltin(PyTypeObject *type);
3131

3232
#ifdef __cplusplus
3333
}

Objects/floatobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include "pycore_object.h" // _PyObject_Init()
1313
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
1414
#include "pycore_pystate.h" // _PyInterpreterState_GET()
15-
#include "pycore_structseq.h" // _PyStructSequence_FiniType()
15+
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
1616

1717
#include <ctype.h>
1818
#include <float.h>
@@ -2029,7 +2029,7 @@ void
20292029
_PyFloat_FiniType(PyInterpreterState *interp)
20302030
{
20312031
if (_Py_IsMainInterpreter(interp)) {
2032-
_PyStructSequence_FiniType(&FloatInfoType);
2032+
_PyStructSequence_FiniBuiltin(&FloatInfoType);
20332033
}
20342034
}
20352035

Objects/longobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include "pycore_object.h" // _PyObject_Init()
1010
#include "pycore_pystate.h" // _Py_IsMainInterpreter()
1111
#include "pycore_runtime.h" // _PY_NSMALLPOSINTS
12-
#include "pycore_structseq.h" // _PyStructSequence_FiniType()
12+
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
1313

1414
#include <ctype.h>
1515
#include <float.h>
@@ -6367,5 +6367,5 @@ _PyLong_FiniTypes(PyInterpreterState *interp)
63676367
return;
63686368
}
63696369

6370-
_PyStructSequence_FiniType(&Int_InfoType);
6370+
_PyStructSequence_FiniBuiltin(&Int_InfoType);
63716371
}

Objects/structseq.c

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -433,12 +433,10 @@ initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict,
433433

434434
static PyMemberDef *
435435
initialize_members(PyStructSequence_Desc *desc,
436-
Py_ssize_t *pn_members, Py_ssize_t *pn_unnamed_members)
436+
Py_ssize_t n_members, Py_ssize_t n_unnamed_members)
437437
{
438438
PyMemberDef *members;
439-
Py_ssize_t n_members, n_unnamed_members;
440439

441-
n_members = count_members(desc, &n_unnamed_members);
442440
members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1);
443441
if (members == NULL) {
444442
PyErr_NoMemory();
@@ -463,8 +461,6 @@ initialize_members(PyStructSequence_Desc *desc,
463461
}
464462
members[k].name = NULL;
465463

466-
*pn_members = n_members;
467-
*pn_unnamed_members = n_unnamed_members;
468464
return members;
469465
}
470466

@@ -510,39 +506,58 @@ _PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type,
510506
PyStructSequence_Desc *desc,
511507
unsigned long tp_flags)
512508
{
513-
if (type->tp_flags & Py_TPFLAGS_READY) {
514-
if (_PyStaticType_InitBuiltin(type) < 0) {
515-
goto failed_init_builtin;
509+
Py_ssize_t n_unnamed_members;
510+
Py_ssize_t n_members = count_members(desc, &n_unnamed_members);
511+
PyMemberDef *members = NULL;
512+
513+
int initialized = 1;
514+
if ((type->tp_flags & Py_TPFLAGS_READY) == 0) {
515+
assert(type->tp_name == NULL);
516+
assert(type->tp_members == NULL);
517+
assert(type->tp_base == NULL);
518+
519+
members = initialize_members(desc, n_members, n_unnamed_members);
520+
if (members == NULL) {
521+
goto error;
516522
}
517-
return 0;
518-
}
523+
initialize_static_fields(type, desc, members, tp_flags);
519524

520-
PyMemberDef *members;
521-
Py_ssize_t n_members, n_unnamed_members;
522-
523-
members = initialize_members(desc, &n_members, &n_unnamed_members);
524-
if (members == NULL) {
525-
return -1;
525+
_Py_SetImmortal(type);
526+
initialized = 0;
527+
}
528+
#ifndef NDEBUG
529+
else {
530+
// Ensure that the type was initialized.
531+
assert(type->tp_name != NULL);
532+
assert(type->tp_members != NULL);
533+
assert(type->tp_base == &PyTuple_Type);
534+
assert((type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
535+
assert(_Py_IsImmortal(type));
526536
}
527-
initialize_static_fields(type, desc, members, tp_flags);
537+
#endif
528538

529-
Py_INCREF(type); // XXX It should be immortal.
530539
if (_PyStaticType_InitBuiltin(type) < 0) {
531-
PyMem_Free(members);
532-
goto failed_init_builtin;
540+
PyErr_Format(PyExc_RuntimeError,
541+
"Can't initialize builtin type %s",
542+
desc->name);
543+
goto error;
544+
}
545+
// This should be dropped if tp_dict is made per-interpreter.
546+
if (initialized) {
547+
return 0;
533548
}
534549

535550
if (initialize_structseq_dict(
536551
desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
537-
PyMem_Free(members);
538-
return -1;
552+
goto error;
539553
}
554+
540555
return 0;
541556

542-
failed_init_builtin:
543-
PyErr_Format(PyExc_RuntimeError,
544-
"Can't initialize builtin type %s",
545-
desc->name);
557+
error:
558+
if (members != NULL) {
559+
PyMem_Free(members);
560+
}
546561
return -1;
547562
}
548563

@@ -566,7 +581,8 @@ PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
566581
return -1;
567582
}
568583

569-
members = initialize_members(desc, &n_members, &n_unnamed_members);
584+
n_members = count_members(desc, &n_unnamed_members);
585+
members = initialize_members(desc, n_members, n_unnamed_members);
570586
if (members == NULL) {
571587
return -1;
572588
}
@@ -585,35 +601,32 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
585601
}
586602

587603

604+
/* This is exposed in the internal API, not the public API.
605+
It is only called on builtin static types, which are all
606+
initialized via _PyStructSequence_InitBuiltinWithFlags(). */
607+
588608
void
589-
_PyStructSequence_FiniType(PyTypeObject *type)
609+
_PyStructSequence_FiniBuiltin(PyTypeObject *type)
590610
{
591611
// Ensure that the type is initialized
592612
assert(type->tp_name != NULL);
593613
assert(type->tp_base == &PyTuple_Type);
614+
assert((type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
615+
assert(_Py_IsImmortal(type));
594616

595617
// Cannot delete a type if it still has subclasses
596618
if (_PyType_HasSubclasses(type)) {
619+
// XXX Shouldn't this be an error?
597620
return;
598621
}
599622

600-
// Undo PyStructSequence_NewType()
601-
type->tp_name = NULL;
602-
PyMem_Free(type->tp_members);
603-
604623
_PyStaticType_Dealloc(type);
605-
assert(Py_REFCNT(type) == 1);
606-
// Undo Py_INCREF(type) of _PyStructSequence_InitType().
607-
// Don't use Py_DECREF(): static type must not be deallocated
608-
Py_SET_REFCNT(type, 0);
609-
#ifdef Py_REF_DEBUG
610-
_Py_DecRefTotal(_PyInterpreterState_GET());
611-
#endif
612624

613-
// Make sure that _PyStructSequence_InitType() will initialize
614-
// the type again
615-
assert(Py_REFCNT(type) == 0);
616-
assert(type->tp_name == NULL);
625+
// Undo _PyStructSequence_InitBuiltinWithFlags().
626+
type->tp_name = NULL;
627+
PyMem_Free(type->tp_members);
628+
type->tp_members = NULL;
629+
type->tp_base = NULL;
617630
}
618631

619632

@@ -627,7 +640,8 @@ _PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags)
627640
Py_ssize_t n_members, n_unnamed_members;
628641

629642
/* Initialize MemberDefs */
630-
members = initialize_members(desc, &n_members, &n_unnamed_members);
643+
n_members = count_members(desc, &n_unnamed_members);
644+
members = initialize_members(desc, n_members, n_unnamed_members);
631645
if (members == NULL) {
632646
return NULL;
633647
}

Objects/typeobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7031,6 +7031,7 @@ PyType_Ready(PyTypeObject *type)
70317031
int
70327032
_PyStaticType_InitBuiltin(PyTypeObject *self)
70337033
{
7034+
assert(_Py_IsImmortal((PyObject *)self));
70347035
assert(!(self->tp_flags & Py_TPFLAGS_HEAPTYPE));
70357036

70367037
if (self->tp_flags & Py_TPFLAGS_READY) {

Python/errors.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "pycore_initconfig.h" // _PyStatus_ERR()
77
#include "pycore_pyerrors.h" // _PyErr_Format()
88
#include "pycore_pystate.h" // _PyThreadState_GET()
9-
#include "pycore_structseq.h" // _PyStructSequence_FiniType()
9+
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
1010
#include "pycore_sysmodule.h" // _PySys_Audit()
1111
#include "pycore_traceback.h" // _PyTraceBack_FromFrame()
1212

@@ -1357,7 +1357,7 @@ _PyErr_FiniTypes(PyInterpreterState *interp)
13571357
return;
13581358
}
13591359

1360-
_PyStructSequence_FiniType(&UnraisableHookArgsType);
1360+
_PyStructSequence_FiniBuiltin(&UnraisableHookArgsType);
13611361
}
13621362

13631363

Python/sysmodule.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3492,13 +3492,13 @@ void
34923492
_PySys_Fini(PyInterpreterState *interp)
34933493
{
34943494
if (_Py_IsMainInterpreter(interp)) {
3495-
_PyStructSequence_FiniType(&VersionInfoType);
3496-
_PyStructSequence_FiniType(&FlagsType);
3495+
_PyStructSequence_FiniBuiltin(&VersionInfoType);
3496+
_PyStructSequence_FiniBuiltin(&FlagsType);
34973497
#if defined(MS_WINDOWS)
3498-
_PyStructSequence_FiniType(&WindowsVersionType);
3498+
_PyStructSequence_FiniBuiltin(&WindowsVersionType);
34993499
#endif
3500-
_PyStructSequence_FiniType(&Hash_InfoType);
3501-
_PyStructSequence_FiniType(&AsyncGenHooksType);
3500+
_PyStructSequence_FiniBuiltin(&Hash_InfoType);
3501+
_PyStructSequence_FiniBuiltin(&AsyncGenHooksType);
35023502
#ifdef __EMSCRIPTEN__
35033503
Py_CLEAR(EmscriptenInfoType);
35043504
#endif

Python/thread.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
#include "Python.h"
99
#include "pycore_pystate.h" // _PyInterpreterState_GET()
10-
#include "pycore_structseq.h" // _PyStructSequence_FiniType()
10+
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
1111
#include "pycore_pythread.h"
1212

1313
#ifndef DONT_HAVE_STDIO_H
@@ -195,5 +195,5 @@ _PyThread_FiniType(PyInterpreterState *interp)
195195
return;
196196
}
197197

198-
_PyStructSequence_FiniType(&ThreadInfoType);
198+
_PyStructSequence_FiniBuiltin(&ThreadInfoType);
199199
}

0 commit comments

Comments
 (0)