Skip to content

Commit 442ad74

Browse files
authored
bpo-43687: Py_Initialize() creates singletons earlier (GH-25147)
Reorganize pycore_interp_init() to initialize singletons before the the first PyType_Ready() call. Fix an issue when Python is configured using --without-doc-strings.
1 parent 58384c6 commit 442ad74

File tree

8 files changed

+128
-85
lines changed

8 files changed

+128
-85
lines changed

Include/internal/pycore_long.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ static inline PyObject* __PyLong_GetSmallInt_internal(int value)
1818
assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS);
1919
size_t index = _PY_NSMALLNEGINTS + value;
2020
PyObject *obj = (PyObject*)interp->small_ints[index];
21-
// _PyLong_GetZero() and _PyLong_GetOne() must not be called
22-
// before _PyLong_Init() nor after _PyLong_Fini()
21+
// _PyLong_GetZero(), _PyLong_GetOne() and get_small_int() must not be
22+
// called before _PyLong_Init() nor after _PyLong_Fini().
2323
assert(obj != NULL);
2424
return obj;
2525
}

Include/internal/pycore_pylifecycle.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
5050
/* Various one-time initializers */
5151

5252
extern PyStatus _PyUnicode_Init(PyInterpreterState *interp);
53+
extern PyStatus _PyUnicode_InitTypes(void);
5354
extern PyStatus _PyBytes_Init(PyInterpreterState *interp);
5455
extern int _PyStructSequence_Init(void);
5556
extern int _PyLong_Init(PyInterpreterState *interp);
57+
extern int _PyLong_InitTypes(void);
5658
extern PyStatus _PyTuple_Init(PyInterpreterState *interp);
5759
extern PyStatus _PyFaulthandler_Init(int enable);
5860
extern int _PyTraceMalloc_Init(int enable);
@@ -64,9 +66,10 @@ extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
6466
extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
6567
extern int _PySys_UpdateConfig(PyThreadState *tstate);
6668
extern PyStatus _PyExc_Init(PyInterpreterState *interp);
67-
extern PyStatus _PyErr_Init(void);
69+
extern PyStatus _PyErr_InitTypes(void);
6870
extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
69-
extern int _PyFloat_Init(void);
71+
extern void _PyFloat_Init(void);
72+
extern int _PyFloat_InitTypes(void);
7073
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
7174

7275
extern PyStatus _PyTypes_Init(void);

Objects/floatobject.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -1968,7 +1968,7 @@ PyTypeObject PyFloat_Type = {
19681968
.tp_vectorcall = (vectorcallfunc)float_vectorcall,
19691969
};
19701970

1971-
int
1971+
void
19721972
_PyFloat_Init(void)
19731973
{
19741974
/* We attempt to determine if this machine is using IEEE
@@ -2016,14 +2016,18 @@ _PyFloat_Init(void)
20162016

20172017
double_format = detected_double_format;
20182018
float_format = detected_float_format;
2019+
}
20192020

2021+
int
2022+
_PyFloat_InitTypes(void)
2023+
{
20202024
/* Init float info */
20212025
if (FloatInfoType.tp_name == NULL) {
20222026
if (PyStructSequence_InitType2(&FloatInfoType, &floatinfo_desc) < 0) {
2023-
return 0;
2027+
return -1;
20242028
}
20252029
}
2026-
return 1;
2030+
return 0;
20272031
}
20282032

20292033
void

Objects/longobject.c

+11-8
Original file line numberDiff line numberDiff line change
@@ -5719,17 +5719,20 @@ _PyLong_Init(PyInterpreterState *interp)
57195719

57205720
interp->small_ints[i] = v;
57215721
}
5722+
return 0;
5723+
}
57225724

5723-
if (_Py_IsMainInterpreter(interp)) {
5724-
/* initialize int_info */
5725-
if (Int_InfoType.tp_name == NULL) {
5726-
if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) {
5727-
return 0;
5728-
}
5725+
5726+
int
5727+
_PyLong_InitTypes(void)
5728+
{
5729+
/* initialize int_info */
5730+
if (Int_InfoType.tp_name == NULL) {
5731+
if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) {
5732+
return -1;
57295733
}
57305734
}
5731-
5732-
return 1;
5735+
return 0;
57335736
}
57345737

57355738
void

Objects/structseq.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,8 @@ int _PyStructSequence_Init(void)
579579
if (_PyUnicode_FromId(&PyId_n_sequence_fields) == NULL
580580
|| _PyUnicode_FromId(&PyId_n_fields) == NULL
581581
|| _PyUnicode_FromId(&PyId_n_unnamed_fields) == NULL)
582+
{
582583
return -1;
583-
584+
}
584585
return 0;
585586
}

Objects/unicodeobject.c

+28-24
Original file line numberDiff line numberDiff line change
@@ -15676,42 +15676,46 @@ PyTypeObject PyUnicode_Type = {
1567615676
PyStatus
1567715677
_PyUnicode_Init(PyInterpreterState *interp)
1567815678
{
15679-
/* XXX - move this array to unicodectype.c ? */
15680-
const Py_UCS2 linebreak[] = {
15681-
0x000A, /* LINE FEED */
15682-
0x000D, /* CARRIAGE RETURN */
15683-
0x001C, /* FILE SEPARATOR */
15684-
0x001D, /* GROUP SEPARATOR */
15685-
0x001E, /* RECORD SEPARATOR */
15686-
0x0085, /* NEXT LINE */
15687-
0x2028, /* LINE SEPARATOR */
15688-
0x2029, /* PARAGRAPH SEPARATOR */
15689-
};
15690-
1569115679
struct _Py_unicode_state *state = &interp->unicode;
1569215680
if (unicode_create_empty_string_singleton(state) < 0) {
1569315681
return _PyStatus_NO_MEMORY();
1569415682
}
1569515683

1569615684
if (_Py_IsMainInterpreter(interp)) {
1569715685
/* initialize the linebreak bloom filter */
15686+
const Py_UCS2 linebreak[] = {
15687+
0x000A, /* LINE FEED */
15688+
0x000D, /* CARRIAGE RETURN */
15689+
0x001C, /* FILE SEPARATOR */
15690+
0x001D, /* GROUP SEPARATOR */
15691+
0x001E, /* RECORD SEPARATOR */
15692+
0x0085, /* NEXT LINE */
15693+
0x2028, /* LINE SEPARATOR */
15694+
0x2029, /* PARAGRAPH SEPARATOR */
15695+
};
1569815696
bloom_linebreak = make_bloom_mask(
1569915697
PyUnicode_2BYTE_KIND, linebreak,
1570015698
Py_ARRAY_LENGTH(linebreak));
15699+
}
1570115700

15702-
if (PyType_Ready(&PyUnicode_Type) < 0) {
15703-
return _PyStatus_ERR("Can't initialize unicode type");
15704-
}
15701+
return _PyStatus_OK();
15702+
}
1570515703

15706-
if (PyType_Ready(&EncodingMapType) < 0) {
15707-
return _PyStatus_ERR("Can't initialize encoding map type");
15708-
}
15709-
if (PyType_Ready(&PyFieldNameIter_Type) < 0) {
15710-
return _PyStatus_ERR("Can't initialize field name iterator type");
15711-
}
15712-
if (PyType_Ready(&PyFormatterIter_Type) < 0) {
15713-
return _PyStatus_ERR("Can't initialize formatter iter type");
15714-
}
15704+
15705+
PyStatus
15706+
_PyUnicode_InitTypes(void)
15707+
{
15708+
if (PyType_Ready(&PyUnicode_Type) < 0) {
15709+
return _PyStatus_ERR("Can't initialize unicode type");
15710+
}
15711+
if (PyType_Ready(&EncodingMapType) < 0) {
15712+
return _PyStatus_ERR("Can't initialize encoding map type");
15713+
}
15714+
if (PyType_Ready(&PyFieldNameIter_Type) < 0) {
15715+
return _PyStatus_ERR("Can't initialize field name iterator type");
15716+
}
15717+
if (PyType_Ready(&PyFormatterIter_Type) < 0) {
15718+
return _PyStatus_ERR("Can't initialize formatter iter type");
1571515719
}
1571615720
return _PyStatus_OK();
1571715721
}

Python/errors.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,7 @@ static PyStructSequence_Desc UnraisableHookArgs_desc = {
11921192

11931193

11941194
PyStatus
1195-
_PyErr_Init(void)
1195+
_PyErr_InitTypes(void)
11961196
{
11971197
if (UnraisableHookArgsType.tp_name == NULL) {
11981198
if (PyStructSequence_InitType2(&UnraisableHookArgsType,

Python/pylifecycle.c

+72-44
Original file line numberDiff line numberDiff line change
@@ -628,61 +628,75 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
628628

629629

630630
static PyStatus
631-
pycore_init_types(PyInterpreterState *interp)
631+
pycore_init_singletons(PyInterpreterState *interp)
632632
{
633633
PyStatus status;
634-
int is_main_interp = _Py_IsMainInterpreter(interp);
635634

636-
status = _PyGC_Init(interp);
635+
if (_PyLong_Init(interp) < 0) {
636+
return _PyStatus_ERR("can't init longs");
637+
}
638+
639+
if (_Py_IsMainInterpreter(interp)) {
640+
_PyFloat_Init();
641+
}
642+
643+
status = _PyBytes_Init(interp);
644+
if (_PyStatus_EXCEPTION(status)) {
645+
return status;
646+
}
647+
648+
status = _PyUnicode_Init(interp);
637649
if (_PyStatus_EXCEPTION(status)) {
638650
return status;
639651
}
640652

641-
// Create the empty tuple singleton. It must be created before the first
642-
// PyType_Ready() call since PyType_Ready() creates tuples, for tp_bases
643-
// for example.
644653
status = _PyTuple_Init(interp);
645654
if (_PyStatus_EXCEPTION(status)) {
646655
return status;
647656
}
648657

658+
return _PyStatus_OK();
659+
}
660+
661+
662+
static PyStatus
663+
pycore_init_types(PyInterpreterState *interp)
664+
{
665+
PyStatus status;
666+
int is_main_interp = _Py_IsMainInterpreter(interp);
667+
649668
if (is_main_interp) {
669+
if (_PyStructSequence_Init() < 0) {
670+
return _PyStatus_ERR("can't initialize structseq");
671+
}
672+
650673
status = _PyTypes_Init();
651674
if (_PyStatus_EXCEPTION(status)) {
652675
return status;
653676
}
654-
}
655677

656-
if (!_PyLong_Init(interp)) {
657-
return _PyStatus_ERR("can't init longs");
658-
}
678+
if (_PyLong_InitTypes() < 0) {
679+
return _PyStatus_ERR("can't init int type");
680+
}
659681

660-
status = _PyUnicode_Init(interp);
661-
if (_PyStatus_EXCEPTION(status)) {
662-
return status;
682+
status = _PyUnicode_InitTypes();
683+
if (_PyStatus_EXCEPTION(status)) {
684+
return status;
685+
}
663686
}
664687

665-
status = _PyBytes_Init(interp);
666-
if (_PyStatus_EXCEPTION(status)) {
667-
return status;
688+
if (is_main_interp) {
689+
if (_PyFloat_InitTypes() < 0) {
690+
return _PyStatus_ERR("can't init float");
691+
}
668692
}
669693

670694
status = _PyExc_Init(interp);
671695
if (_PyStatus_EXCEPTION(status)) {
672696
return status;
673697
}
674698

675-
if (is_main_interp) {
676-
if (!_PyFloat_Init()) {
677-
return _PyStatus_ERR("can't init float");
678-
}
679-
680-
if (_PyStructSequence_Init() < 0) {
681-
return _PyStatus_ERR("can't initialize structseq");
682-
}
683-
}
684-
685-
status = _PyErr_Init();
699+
status = _PyErr_InitTypes();
686700
if (_PyStatus_EXCEPTION(status)) {
687701
return status;
688702
}
@@ -693,22 +707,15 @@ pycore_init_types(PyInterpreterState *interp)
693707
}
694708
}
695709

696-
if (_PyWarnings_InitState(interp) < 0) {
697-
return _PyStatus_ERR("can't initialize warnings");
698-
}
699-
700-
status = _PyAtExit_Init(interp);
701-
if (_PyStatus_EXCEPTION(status)) {
702-
return status;
703-
}
704-
705710
return _PyStatus_OK();
706711
}
707712

708713

709714
static PyStatus
710-
pycore_init_builtins(PyInterpreterState *interp)
715+
pycore_init_builtins(PyThreadState *tstate)
711716
{
717+
PyInterpreterState *interp = tstate->interp;
718+
712719
PyObject *bimod = _PyBuiltin_Init(interp);
713720
if (bimod == NULL) {
714721
goto error;
@@ -744,6 +751,7 @@ pycore_init_builtins(PyInterpreterState *interp)
744751
}
745752
interp->import_func = Py_NewRef(import_func);
746753

754+
assert(!_PyErr_Occurred(tstate));
747755
return _PyStatus_OK();
748756

749757
error:
@@ -755,29 +763,49 @@ pycore_init_builtins(PyInterpreterState *interp)
755763
static PyStatus
756764
pycore_interp_init(PyThreadState *tstate)
757765
{
766+
PyInterpreterState *interp = tstate->interp;
758767
PyStatus status;
759768
PyObject *sysmod = NULL;
760769

761-
status = pycore_init_types(tstate->interp);
770+
// Create singletons before the first PyType_Ready() call, since
771+
// PyType_Ready() uses singletons like the Unicode empty string (tp_doc)
772+
// and the empty tuple singletons (tp_bases).
773+
status = pycore_init_singletons(interp);
762774
if (_PyStatus_EXCEPTION(status)) {
763-
goto done;
775+
return status;
764776
}
765777

766-
status = _PySys_Create(tstate, &sysmod);
778+
// The GC must be initialized before the first GC collection.
779+
status = _PyGC_Init(interp);
780+
if (_PyStatus_EXCEPTION(status)) {
781+
return status;
782+
}
783+
784+
status = pycore_init_types(interp);
767785
if (_PyStatus_EXCEPTION(status)) {
768786
goto done;
769787
}
770788

771-
assert(!_PyErr_Occurred(tstate));
789+
if (_PyWarnings_InitState(interp) < 0) {
790+
return _PyStatus_ERR("can't initialize warnings");
791+
}
792+
793+
status = _PyAtExit_Init(interp);
794+
if (_PyStatus_EXCEPTION(status)) {
795+
return status;
796+
}
772797

773-
status = pycore_init_builtins(tstate->interp);
798+
status = _PySys_Create(tstate, &sysmod);
774799
if (_PyStatus_EXCEPTION(status)) {
775800
goto done;
776801
}
777802

778-
assert(!_PyErr_Occurred(tstate));
803+
status = pycore_init_builtins(tstate);
804+
if (_PyStatus_EXCEPTION(status)) {
805+
goto done;
806+
}
779807

780-
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
808+
const PyConfig *config = _PyInterpreterState_GetConfig(interp);
781809
if (config->_install_importlib) {
782810
/* This call sets up builtin and frozen import support */
783811
if (init_importlib(tstate, sysmod) < 0) {

0 commit comments

Comments
 (0)