|
14 | 14 |
|
15 | 15 | #include "frameobject.h" // PyFrame_New() |
16 | 16 | #include "marshal.h" // PyMarshal_WriteLongToFile() |
| 17 | +#include "pyerrors.h" |
17 | 18 | #include "pylifecycle.h" |
18 | 19 | #include "pystate.h" |
19 | 20 |
|
@@ -2656,6 +2657,10 @@ test_thread_state_ensure_crossinterp(PyObject *self, PyObject *unused) |
2656 | 2657 | PyInterpreterRef ref = get_strong_ref(); |
2657 | 2658 | PyThreadState *save_tstate = PyThreadState_Swap(NULL); |
2658 | 2659 | PyThreadState *interp_tstate = Py_NewInterpreter(); |
| 2660 | + if (interp_tstate == NULL) { |
| 2661 | + PyInterpreterRef_Close(ref); |
| 2662 | + return PyErr_NoMemory(); |
| 2663 | + } |
2659 | 2664 |
|
2660 | 2665 | /* This should create a new thread state for the calling interpreter, *not* |
2661 | 2666 | reactivate the old one. In a real-world scenario, this would arise in |
@@ -2702,6 +2707,36 @@ test_thread_state_ensure_crossinterp(PyObject *self, PyObject *unused) |
2702 | 2707 | Py_RETURN_NONE; |
2703 | 2708 | } |
2704 | 2709 |
|
| 2710 | +static PyObject * |
| 2711 | +test_weak_interpreter_ref_after_shutdown(PyObject *self, PyObject *unused) |
| 2712 | +{ |
| 2713 | + PyThreadState *save_tstate = PyThreadState_Swap(NULL); |
| 2714 | + PyInterpreterWeakRef wref; |
| 2715 | + PyThreadState *interp_tstate = Py_NewInterpreter(); |
| 2716 | + if (interp_tstate == NULL) { |
| 2717 | + return PyErr_NoMemory(); |
| 2718 | + } |
| 2719 | + |
| 2720 | + int res = PyInterpreterWeakRef_Get(&wref); |
| 2721 | + (void)res; |
| 2722 | + assert(res == 0); |
| 2723 | + |
| 2724 | + // As a sanity check, ensure that the weakref actually works |
| 2725 | + PyInterpreterRef ref; |
| 2726 | + res = PyInterpreterWeakRef_AsStrong(wref, &ref); |
| 2727 | + assert(res == 0); |
| 2728 | + PyInterpreterRef_Close(ref); |
| 2729 | + |
| 2730 | + // Now, destroy the interpreter and try to acquire a weak reference. |
| 2731 | + // It should fail. |
| 2732 | + Py_EndInterpreter(interp_tstate); |
| 2733 | + res = PyInterpreterWeakRef_AsStrong(wref, &ref); |
| 2734 | + assert(res == -1); |
| 2735 | + |
| 2736 | + PyThreadState_Swap(save_tstate); |
| 2737 | + Py_RETURN_NONE; |
| 2738 | +} |
| 2739 | + |
2705 | 2740 | static PyMethodDef TestMethods[] = { |
2706 | 2741 | {"set_errno", set_errno, METH_VARARGS}, |
2707 | 2742 | {"test_config", test_config, METH_NOARGS}, |
@@ -2799,6 +2834,7 @@ static PyMethodDef TestMethods[] = { |
2799 | 2834 | {"test_interpreter_refs", test_interpreter_refs, METH_NOARGS}, |
2800 | 2835 | {"test_thread_state_ensure_nested", test_thread_state_ensure_nested, METH_NOARGS}, |
2801 | 2836 | {"test_thread_state_ensure_crossinterp", test_thread_state_ensure_crossinterp, METH_NOARGS}, |
| 2837 | + {"test_weak_interpreter_ref_after_shutdown", test_weak_interpreter_ref_after_shutdown, METH_NOARGS}, |
2802 | 2838 | {NULL, NULL} /* sentinel */ |
2803 | 2839 | }; |
2804 | 2840 |
|
|
0 commit comments