@@ -1063,22 +1063,22 @@ _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
1063
1063
/* Module functions */
1064
1064
1065
1065
struct bootstate {
1066
- PyInterpreterState * interp ;
1066
+ PyThreadState * tstate ;
1067
1067
PyObject * func ;
1068
1068
PyObject * args ;
1069
1069
PyObject * kwargs ;
1070
- PyThreadState * tstate ;
1071
- _PyRuntimeState * runtime ;
1072
1070
};
1073
1071
1074
1072
1075
1073
static void
1076
- thread_bootstate_free (struct bootstate * boot )
1074
+ thread_bootstate_free (struct bootstate * boot , int decref )
1077
1075
{
1078
- Py_DECREF (boot -> func );
1079
- Py_DECREF (boot -> args );
1080
- Py_XDECREF (boot -> kwargs );
1081
- PyMem_Free (boot );
1076
+ if (decref ) {
1077
+ Py_DECREF (boot -> func );
1078
+ Py_DECREF (boot -> args );
1079
+ Py_XDECREF (boot -> kwargs );
1080
+ }
1081
+ PyMem_RawFree (boot );
1082
1082
}
1083
1083
1084
1084
@@ -1088,9 +1088,24 @@ thread_run(void *boot_raw)
1088
1088
struct bootstate * boot = (struct bootstate * ) boot_raw ;
1089
1089
PyThreadState * tstate = boot -> tstate ;
1090
1090
1091
- // gh-104690: If Python is being finalized and PyInterpreterState_Delete()
1092
- // was called, tstate becomes a dangling pointer.
1093
- assert (_PyThreadState_CheckConsistency (tstate ));
1091
+ // gh-108987: If _thread.start_new_thread() is called before or while
1092
+ // Python is being finalized, thread_run() can called *after*.
1093
+ // _PyRuntimeState_SetFinalizing() is called. At this point, all Python
1094
+ // threads must exit, except of the thread calling Py_Finalize() whch holds
1095
+ // the GIL and must not exit.
1096
+ //
1097
+ // At this stage, tstate can be a dangling pointer (point to freed memory),
1098
+ // it's ok to call _PyThreadState_MustExit() with a dangling pointer.
1099
+ if (_PyThreadState_MustExit (tstate )) {
1100
+ // Don't call PyThreadState_Clear() nor _PyThreadState_DeleteCurrent().
1101
+ // These functions are called on tstate indirectly by Py_Finalize()
1102
+ // which calls _PyInterpreterState_Clear().
1103
+ //
1104
+ // Py_DECREF() cannot be called because the GIL is not held: leak
1105
+ // references on purpose. Python is being finalized anyway.
1106
+ thread_bootstate_free (boot , 0 );
1107
+ goto exit ;
1108
+ }
1094
1109
1095
1110
_PyThreadState_Bind (tstate );
1096
1111
PyEval_AcquireThread (tstate );
@@ -1109,14 +1124,17 @@ thread_run(void *boot_raw)
1109
1124
Py_DECREF (res );
1110
1125
}
1111
1126
1112
- thread_bootstate_free (boot );
1127
+ thread_bootstate_free (boot , 1 );
1128
+
1113
1129
tstate -> interp -> threads .count -- ;
1114
1130
PyThreadState_Clear (tstate );
1115
1131
_PyThreadState_DeleteCurrent (tstate );
1116
1132
1133
+ exit :
1117
1134
// bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with
1118
1135
// the glibc, pthread_exit() can abort the whole process if dlopen() fails
1119
1136
// to open the libgcc_s.so library (ex: EMFILE error).
1137
+ return ;
1120
1138
}
1121
1139
1122
1140
static PyObject *
@@ -1140,7 +1158,6 @@ and False otherwise.\n");
1140
1158
static PyObject *
1141
1159
thread_PyThread_start_new_thread (PyObject * self , PyObject * fargs )
1142
1160
{
1143
- _PyRuntimeState * runtime = & _PyRuntime ;
1144
1161
PyObject * func , * args , * kwargs = NULL ;
1145
1162
1146
1163
if (!PyArg_UnpackTuple (fargs , "start_new_thread" , 2 , 3 ,
@@ -1179,20 +1196,21 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
1179
1196
return NULL ;
1180
1197
}
1181
1198
1182
- struct bootstate * boot = PyMem_NEW (struct bootstate , 1 );
1199
+ // gh-109795: Use PyMem_RawMalloc() instead of PyMem_Malloc(),
1200
+ // because it should be possible to call thread_bootstate_free()
1201
+ // without holding the GIL.
1202
+ struct bootstate * boot = PyMem_RawMalloc (sizeof (struct bootstate ));
1183
1203
if (boot == NULL ) {
1184
1204
return PyErr_NoMemory ();
1185
1205
}
1186
- boot -> interp = _PyInterpreterState_GET ();
1187
- boot -> tstate = _PyThreadState_New (boot -> interp );
1206
+ boot -> tstate = _PyThreadState_New (interp );
1188
1207
if (boot -> tstate == NULL ) {
1189
- PyMem_Free (boot );
1208
+ PyMem_RawFree (boot );
1190
1209
if (!PyErr_Occurred ()) {
1191
1210
return PyErr_NoMemory ();
1192
1211
}
1193
1212
return NULL ;
1194
1213
}
1195
- boot -> runtime = runtime ;
1196
1214
boot -> func = Py_NewRef (func );
1197
1215
boot -> args = Py_NewRef (args );
1198
1216
boot -> kwargs = Py_XNewRef (kwargs );
@@ -1201,7 +1219,7 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
1201
1219
if (ident == PYTHREAD_INVALID_THREAD_ID ) {
1202
1220
PyErr_SetString (ThreadError , "can't start new thread" );
1203
1221
PyThreadState_Clear (boot -> tstate );
1204
- thread_bootstate_free (boot );
1222
+ thread_bootstate_free (boot , 1 );
1205
1223
return NULL ;
1206
1224
}
1207
1225
return PyLong_FromUnsignedLong (ident );
0 commit comments