|
18 | 18 | #include "eval.h" |
19 | 19 | #include "marshal.h" |
20 | 20 | #include "osdefs.h" |
| 21 | +#include "abstract.h" |
21 | 22 |
|
22 | 23 | #ifdef HAVE_SIGNAL_H |
23 | 24 | #include <signal.h> |
@@ -66,6 +67,7 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, |
66 | 67 | static void err_input(perrdetail *); |
67 | 68 | static void initsigs(void); |
68 | 69 | static void call_py_exitfuncs(void); |
| 70 | +static void wait_for_thread_shutdown(void); |
69 | 71 | static void call_ll_exitfuncs(void); |
70 | 72 | extern void _PyUnicode_Init(void); |
71 | 73 | extern void _PyUnicode_Fini(void); |
@@ -363,6 +365,8 @@ Py_Finalize(void) |
363 | 365 | if (!initialized) |
364 | 366 | return; |
365 | 367 |
|
| 368 | + wait_for_thread_shutdown(); |
| 369 | + |
366 | 370 | /* The interpreter is still entirely intact at this point, and the |
367 | 371 | * exit funcs may be relying on that. In particular, if some thread |
368 | 372 | * or exit func is still waiting to do an import, the import machinery |
@@ -2059,6 +2063,34 @@ call_py_exitfuncs(void) |
2059 | 2063 | PyErr_Clear(); |
2060 | 2064 | } |
2061 | 2065 |
|
| 2066 | +/* Wait until threading._shutdown completes, provided |
| 2067 | + the threading module was imported in the first place. |
| 2068 | + The shutdown routine will wait until all non-daemon |
| 2069 | + "threading" threads have completed. */ |
| 2070 | +static void |
| 2071 | +wait_for_thread_shutdown(void) |
| 2072 | +{ |
| 2073 | +#ifdef WITH_THREAD |
| 2074 | + PyObject *result; |
| 2075 | + PyThreadState *tstate = PyThreadState_GET(); |
| 2076 | + PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, |
| 2077 | + "threading"); |
| 2078 | + if (threading == NULL) { |
| 2079 | + /* threading not imported */ |
| 2080 | + PyErr_Clear(); |
| 2081 | + return; |
| 2082 | + } |
| 2083 | + result = PyObject_CallMethod(threading, "_shutdown", ""); |
| 2084 | + if (result == NULL) { |
| 2085 | + PyErr_WriteUnraisable(threading); |
| 2086 | + } |
| 2087 | + else { |
| 2088 | + Py_DECREF(result); |
| 2089 | + } |
| 2090 | + Py_DECREF(threading); |
| 2091 | +#endif |
| 2092 | +} |
| 2093 | + |
2062 | 2094 | #define NEXITFUNCS 32 |
2063 | 2095 | static void (*exitfuncs[NEXITFUNCS])(void); |
2064 | 2096 | static int nexitfuncs = 0; |
|
0 commit comments