|
2 | 2 | #include "pycore_frame.h" // PyFrameObject |
3 | 3 | #include "pycore_genobject.h" // PyAsyncGenObject |
4 | 4 | #include "pycore_import.h" // _PyImport_GetModules() |
| 5 | +#include "pycore_interp.h" // _PyInterpreterState_GetFinalizing() |
5 | 6 | #include "pycore_interpframe.h" // _PyFrame_GetCode() |
6 | 7 | #include "pycore_long.h" // _PyLong_GetZero() |
7 | 8 | #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() |
@@ -254,27 +255,66 @@ get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import) |
254 | 255 | return obj; |
255 | 256 | } |
256 | 257 |
|
257 | | -void |
258 | | -_PyWarnings_PrepareForFinalization(PyInterpreterState *interp) |
259 | | -{ |
260 | | - WarningsState *st = warnings_get_state(interp); |
261 | | - _PyRecursiveMutex_at_shutdown_reinit(&st->lock); |
262 | | -} |
| 258 | +static _Py_thread_local PyInterpreterGuard warnings_guard; |
263 | 259 |
|
264 | | -static inline void |
| 260 | +static inline int |
265 | 261 | warnings_lock(PyInterpreterState *interp) |
266 | 262 | { |
267 | 263 | WarningsState *st = warnings_get_state(interp); |
268 | 264 | assert(st != NULL); |
| 265 | + if (_PyRecursiveMutex_IsLockedByCurrentThread(&st->lock)) { |
| 266 | + _PyRecursiveMutex_Lock(&st->lock); |
| 267 | + return 0; |
| 268 | + } |
| 269 | + PyInterpreterGuard *guard = NULL; |
| 270 | + if (_PyInterpreterState_GetFinalizing(interp) != _PyThreadState_GET()) { |
| 271 | + guard = &warnings_guard; |
| 272 | + if (guard->interp != NULL) { |
| 273 | + guard = PyMem_RawMalloc(sizeof(*guard)); |
| 274 | + if (guard == NULL) { |
| 275 | + PyErr_NoMemory(); |
| 276 | + return -1; |
| 277 | + } |
| 278 | + } |
| 279 | + if (_PyInterpreterGuard_TryAcquire(interp, guard) < 0) { |
| 280 | + if (guard != &warnings_guard) { |
| 281 | + PyMem_RawFree(guard); |
| 282 | + } |
| 283 | + // Finalization has begun; this thread must stop before it takes |
| 284 | + // the lock. |
| 285 | + _PyThreadState_HangThread(_PyThreadState_GET()); |
| 286 | + } |
| 287 | + } |
269 | 288 | _PyRecursiveMutex_Lock(&st->lock); |
| 289 | + st->lock_guard = guard; |
| 290 | + return 0; |
270 | 291 | } |
271 | 292 |
|
272 | 293 | static inline int |
273 | 294 | warnings_unlock(PyInterpreterState *interp) |
274 | 295 | { |
275 | 296 | WarningsState *st = warnings_get_state(interp); |
276 | 297 | assert(st != NULL); |
277 | | - return _PyRecursiveMutex_TryUnlock(&st->lock); |
| 298 | + if (!_PyRecursiveMutex_IsLockedByCurrentThread(&st->lock)) { |
| 299 | + return -1; |
| 300 | + } |
| 301 | + if (st->lock.level > 0) { |
| 302 | + _PyRecursiveMutex_Unlock(&st->lock); |
| 303 | + return 0; |
| 304 | + } |
| 305 | + PyInterpreterGuard *guard = st->lock_guard; |
| 306 | + st->lock_guard = NULL; |
| 307 | + _PyRecursiveMutex_Unlock(&st->lock); |
| 308 | + if (guard != NULL) { |
| 309 | + _PyInterpreterGuard_Release(guard); |
| 310 | + if (guard == &warnings_guard) { |
| 311 | + guard->interp = NULL; |
| 312 | + } |
| 313 | + else { |
| 314 | + PyMem_RawFree(guard); |
| 315 | + } |
| 316 | + } |
| 317 | + return 0; |
278 | 318 | } |
279 | 319 |
|
280 | 320 | static inline bool |
@@ -358,7 +398,9 @@ warnings_acquire_lock_impl(PyObject *module) |
358 | 398 | if (interp == NULL) { |
359 | 399 | return NULL; |
360 | 400 | } |
361 | | - warnings_lock(interp); |
| 401 | + if (warnings_lock(interp) < 0) { |
| 402 | + return NULL; |
| 403 | + } |
362 | 404 | Py_RETURN_NONE; |
363 | 405 | } |
364 | 406 |
|
@@ -1140,10 +1182,14 @@ do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level, |
1140 | 1182 | &filename, &lineno, &module, ®istry)) |
1141 | 1183 | return NULL; |
1142 | 1184 |
|
1143 | | - warnings_lock(tstate->interp); |
1144 | | - res = warn_explicit(tstate, category, message, filename, lineno, module, registry, |
1145 | | - NULL, source); |
1146 | | - warnings_unlock(tstate->interp); |
| 1185 | + if (warnings_lock(tstate->interp) < 0) { |
| 1186 | + res = NULL; |
| 1187 | + } |
| 1188 | + else { |
| 1189 | + res = warn_explicit(tstate, category, message, filename, lineno, module, registry, |
| 1190 | + NULL, source); |
| 1191 | + warnings_unlock(tstate->interp); |
| 1192 | + } |
1147 | 1193 | Py_DECREF(filename); |
1148 | 1194 | Py_DECREF(registry); |
1149 | 1195 | Py_DECREF(module); |
@@ -1322,10 +1368,14 @@ warnings_warn_explicit_impl(PyObject *module, PyObject *message, |
1322 | 1368 | } |
1323 | 1369 | } |
1324 | 1370 |
|
1325 | | - warnings_lock(tstate->interp); |
1326 | | - returned = warn_explicit(tstate, category, message, filename, lineno, |
1327 | | - mod, registry, source_line, sourceobj); |
1328 | | - warnings_unlock(tstate->interp); |
| 1371 | + if (warnings_lock(tstate->interp) < 0) { |
| 1372 | + returned = NULL; |
| 1373 | + } |
| 1374 | + else { |
| 1375 | + returned = warn_explicit(tstate, category, message, filename, lineno, |
| 1376 | + mod, registry, source_line, sourceobj); |
| 1377 | + warnings_unlock(tstate->interp); |
| 1378 | + } |
1329 | 1379 | Py_XDECREF(source_line); |
1330 | 1380 | return returned; |
1331 | 1381 | } |
@@ -1472,7 +1522,9 @@ PyErr_WarnExplicitObject(PyObject *category, PyObject *message, |
1472 | 1522 | return -1; |
1473 | 1523 | } |
1474 | 1524 |
|
1475 | | - warnings_lock(tstate->interp); |
| 1525 | + if (warnings_lock(tstate->interp) < 0) { |
| 1526 | + return -1; |
| 1527 | + } |
1476 | 1528 | res = warn_explicit(tstate, category, message, filename, lineno, |
1477 | 1529 | module, registry, NULL, NULL); |
1478 | 1530 | warnings_unlock(tstate->interp); |
@@ -1537,19 +1589,17 @@ PyErr_WarnExplicitFormat(PyObject *category, |
1537 | 1589 | va_start(vargs, format); |
1538 | 1590 | message = PyUnicode_FromFormatV(format, vargs); |
1539 | 1591 | if (message != NULL) { |
1540 | | - PyObject *res; |
1541 | 1592 | PyThreadState *tstate = get_current_tstate(); |
1542 | | - if (tstate != NULL) { |
1543 | | - warnings_lock(tstate->interp); |
1544 | | - res = warn_explicit(tstate, category, message, filename, lineno, |
1545 | | - module, registry, NULL, NULL); |
| 1593 | + if (tstate != NULL && warnings_lock(tstate->interp) == 0) { |
| 1594 | + PyObject *res = warn_explicit(tstate, category, message, filename, lineno, |
| 1595 | + module, registry, NULL, NULL); |
1546 | 1596 | warnings_unlock(tstate->interp); |
1547 | | - Py_DECREF(message); |
1548 | 1597 | if (res != NULL) { |
1549 | 1598 | Py_DECREF(res); |
1550 | 1599 | ret = 0; |
1551 | 1600 | } |
1552 | 1601 | } |
| 1602 | + Py_DECREF(message); |
1553 | 1603 | } |
1554 | 1604 | va_end(vargs); |
1555 | 1605 | exit: |
|
0 commit comments