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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy