@@ -2801,6 +2801,81 @@ test_thread_state_ensure_from_view(void)
28012801 return 0 ;
28022802}
28032803
2804+ #define NUM_THREADS 4
2805+
2806+ static void
2807+ stress_func (void * arg )
2808+ {
2809+ PyInterpreterGuard * guard = (PyInterpreterGuard * )arg ;
2810+
2811+ for (int i = 0 ; i < 1000 ; ++ i ) {
2812+ assert (guard != NULL );
2813+ PyThreadStateToken * token = PyThreadState_Ensure (guard );
2814+ assert (token != NULL );
2815+
2816+ PyGILState_STATE gstate = PyGILState_Ensure ();
2817+
2818+ PyInterpreterView * view = PyInterpreterView_FromCurrent ();
2819+ assert (view != NULL );
2820+
2821+ PyThreadStateToken * token2 = PyThreadState_EnsureFromView (view );
2822+ assert (token2 != NULL );
2823+ PyThreadState_Release (token2 );
2824+
2825+ PyGILState_Release (gstate );
2826+
2827+ PyThreadState_Release (token );
2828+
2829+ PyInterpreterGuard_Close (guard );
2830+
2831+ _Py_yield ();
2832+
2833+ guard = PyInterpreterGuard_FromView (view );
2834+ PyInterpreterView_Close (view );
2835+
2836+ if (guard == NULL ) {
2837+ // The interpreter is shutting down. Bail out now.
2838+ return ;
2839+ }
2840+ }
2841+
2842+ PyInterpreterGuard_Close (guard );
2843+ }
2844+
2845+ static int
2846+ test_concurrent_finalization_stress (void )
2847+ {
2848+ for (int j = 0 ; j < 50 ; ++ j ) {
2849+ _testembed_initialize ();
2850+ PyThread_handle_t handles [NUM_THREADS ];
2851+ PyThread_ident_t idents [NUM_THREADS ];
2852+ PyInterpreterGuard * guards [NUM_THREADS ];
2853+
2854+ for (int i = 0 ; i < NUM_THREADS ; ++ i ) {
2855+ guards [i ] = PyInterpreterGuard_FromCurrent ();
2856+ assert (guards [i ] != NULL );
2857+ if (PyThread_start_joinable_thread (stress_func , guards [i ], & idents [i ], & handles [i ]) < 0 ) {
2858+ for (int x = 0 ; x < i ; ++ x ) {
2859+ PyInterpreterGuard_Close (guards [x ]);
2860+ PyThread_detach_thread (handles [x ]);
2861+ }
2862+ return -1 ;
2863+ }
2864+ }
2865+
2866+ _Py_yield ();
2867+ Py_Finalize ();
2868+
2869+ for (int i = 0 ; i < NUM_THREADS ; ++ i ) {
2870+ PyThread_join_thread (handles [i ]);
2871+ }
2872+ }
2873+
2874+ return 0 ;
2875+ }
2876+
2877+ #undef NUM_THREADS
2878+
28042879/* *********************************************************
28052880 * List of test cases and the function that implements it.
28062881 *
@@ -2898,6 +2973,7 @@ static struct TestCase TestCases[] = {
28982973 {"test_thread_state_ensure" , test_thread_state_ensure },
28992974 {"test_main_interpreter_view" , test_main_interpreter_view },
29002975 {"test_thread_state_ensure_from_view" , test_thread_state_ensure_from_view },
2976+ {"test_concurrent_finalization_stress" , test_concurrent_finalization_stress },
29012977 {NULL , NULL }
29022978};
29032979
0 commit comments