|
17 | 17 | #include "ast.h" |
18 | 18 | #include "eval.h" |
19 | 19 | #include "marshal.h" |
| 20 | +#include "abstract.h" |
20 | 21 |
|
21 | 22 | #ifdef HAVE_SIGNAL_H |
22 | 23 | #include <signal.h> |
@@ -61,6 +62,7 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, |
61 | 62 | PyCompilerFlags *); |
62 | 63 | static void err_input(perrdetail *); |
63 | 64 | static void initsigs(void); |
| 65 | +static void wait_for_thread_shutdown(void); |
64 | 66 | static void call_sys_exitfunc(void); |
65 | 67 | static void call_ll_exitfuncs(void); |
66 | 68 | extern void _PyUnicode_Init(void); |
@@ -390,6 +392,8 @@ Py_Finalize(void) |
390 | 392 | if (!initialized) |
391 | 393 | return; |
392 | 394 |
|
| 395 | + wait_for_thread_shutdown(); |
| 396 | + |
393 | 397 | /* The interpreter is still entirely intact at this point, and the |
394 | 398 | * exit funcs may be relying on that. In particular, if some thread |
395 | 399 | * or exit func is still waiting to do an import, the import machinery |
@@ -1666,6 +1670,32 @@ Py_FatalError(const char *msg) |
1666 | 1670 | #include "pythread.h" |
1667 | 1671 | #endif |
1668 | 1672 |
|
| 1673 | +/* Wait until threading._shutdown completes, provided |
| 1674 | + the threading module was imported in the first place. |
| 1675 | + The shutdown routine will wait until all non-daemon |
| 1676 | + "threading" threads have completed. */ |
| 1677 | +static void |
| 1678 | +wait_for_thread_shutdown(void) |
| 1679 | +{ |
| 1680 | +#ifdef WITH_THREAD |
| 1681 | + PyObject *result; |
| 1682 | + PyThreadState *tstate = PyThreadState_GET(); |
| 1683 | + PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, |
| 1684 | + "threading"); |
| 1685 | + if (threading == NULL) { |
| 1686 | + /* threading not imported */ |
| 1687 | + PyErr_Clear(); |
| 1688 | + return; |
| 1689 | + } |
| 1690 | + result = PyObject_CallMethod(threading, "_shutdown", ""); |
| 1691 | + if (result == NULL) |
| 1692 | + PyErr_WriteUnraisable(threading); |
| 1693 | + else |
| 1694 | + Py_DECREF(result); |
| 1695 | + Py_DECREF(threading); |
| 1696 | +#endif |
| 1697 | +} |
| 1698 | + |
1669 | 1699 | #define NEXITFUNCS 32 |
1670 | 1700 | static void (*exitfuncs[NEXITFUNCS])(void); |
1671 | 1701 | static int nexitfuncs = 0; |
|
0 commit comments