@@ -2596,108 +2596,39 @@ def test_unsupported_platform_error(self):
25962596
25972597@requires_remote_subprocess_debugging ()
25982598class TestDetectionOfThreadStatus (RemoteInspectionTestBase ):
2599- def _check_cpu_status_with_multiple_thread_states (
2600- self , * , native = False , subinterpreter = False ,
2601- ):
2599+ @skip_if_not_supported
2600+ def test_cpu_status_with_multiple_thread_states (self ):
26022601 import_module ("_testinternalcapi" )
2603- import_module ("_interpreters" )
2604- if native :
2605- import_module ("_hashlib" )
2606- work = "_hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 10_000_000)"
2607- else :
2608- work = "pass"
2609- code = textwrap .dedent (f"""
2610- import socket
2611- { "import _hashlib" if native else "" }
2612- active_sock = socket.socket(fileno={{fd}})
2613-
2602+ import_module ("_hashlib" )
2603+ code = textwrap .dedent ("""
2604+ import _hashlib
26142605 def active():
2615- active_sock.sendall(b"ready")
26162606 while True:
2617- { work }
2618-
2607+ _hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 10_000_000)
26192608 active()
26202609 """ )
26212610 script = f"""
2622- import _interpreters, _testinternalcapi
2623-
2611+ import _testinternalcapi
26242612 def suspended():
2625- if { subinterpreter } :
2626- interpid = _interpreters.create()
2627- else:
2628- interpid = _interpreters.get_current()[0]
2629- # Create another state on this OS thread.
2630- code = { code !r} .format(fd=sock.fileno())
2631- _testinternalcapi.exec_interpreter(interpid, code)
2632-
2613+ sock.sendall(b"ready")
2614+ _testinternalcapi.exec_interpreter(0, { code !r} )
26332615 suspended()
26342616 """
26352617 with self ._target_process (script ) as (p , sock , _ ):
26362618 _wait_for_signal (sock , b"ready" )
2637- for mode in (PROFILING_MODE_CPU , PROFILING_MODE_ALL ):
2638- with self .subTest (mode = mode ):
2639- unwinder = RemoteUnwinder (
2640- p .pid , all_threads = True , mode = mode ,
2641- skip_non_matching_threads = (mode == PROFILING_MODE_CPU ),
2642- )
2643- for _ in busy_retry (SHORT_TIMEOUT ):
2644- try :
2645- trace = unwinder .get_stack_trace ()
2646- except TRANSIENT_ERRORS :
2647- continue
2648- active = self ._find_thread_with_frame (
2649- trace , lambda f : f .funcname == "active" )
2650- if active is None or not active .status & THREAD_STATUS_ON_CPU :
2651- continue
2652- if native and active .status & THREAD_STATUS_HAS_GIL :
2653- continue
2654- suspended = self ._find_thread_with_frame (
2655- trace , lambda f : f .funcname == "suspended" )
2656- if mode == PROFILING_MODE_CPU :
2657- self .assertIsNone (suspended )
2658- else :
2659- self .assertIsNotNone (suspended )
2660- self .assertEqual (suspended .thread_id , active .thread_id )
2661- self .assertFalse (suspended .status & THREAD_STATUS_ON_CPU )
2662- break
2663-
2664- @skip_if_not_supported
2665- def test_cpu_status_with_multiple_thread_states (self ):
2666- for native in (False , True ):
2667- for subinterpreter in (False , True ):
2668- with self .subTest (native = native , subinterpreter = subinterpreter ):
2669- self ._check_cpu_status_with_multiple_thread_states (
2670- native = native , subinterpreter = subinterpreter )
2671-
2672- @skip_if_not_supported
2673- def test_cpu_status_after_tstate_callback (self ):
2674- import_module ("_testinternalcapi" )
2675- for retain in (False , True ):
2676- with self .subTest (retain = retain ):
2677- script = f"""
2678- import _testinternalcapi
2679-
2680- def ready():
2681- sock.sendall(b"ready")
2682-
2683- def native_work():
2684- _testinternalcapi.native_work_after_tstate_callback(
2685- ready, { SHORT_TIMEOUT * 3 } , { retain } )
2686-
2687- native_work()
2688- """
2689- with self ._target_process (script ) as (p , sock , _ ):
2690- _wait_for_signal (sock , b"ready" )
2691- for mode in (PROFILING_MODE_CPU , PROFILING_MODE_ALL ):
2692- with self .subTest (mode = mode ):
2693- unwinder = RemoteUnwinder (p .pid , all_threads = True , mode = mode )
2694- for _ in busy_retry (SHORT_TIMEOUT ):
2695- trace = _get_stack_trace_with_retry (unwinder )
2696- thread = self ._find_thread_with_frame (
2697- trace , lambda f : f .funcname == "native_work" )
2698- if thread and thread .status & THREAD_STATUS_ON_CPU :
2699- self .assertFalse (thread .status & THREAD_STATUS_HAS_GIL )
2700- break
2619+ unwinder = RemoteUnwinder (p .pid , all_threads = True , mode = PROFILING_MODE_ALL )
2620+ for _ in busy_retry (SHORT_TIMEOUT ):
2621+ trace = _get_stack_trace_with_retry (unwinder )
2622+ active = self ._find_thread_with_frame (trace , lambda f : f .funcname == "active" )
2623+ if active is None or not active .status & THREAD_STATUS_ON_CPU :
2624+ continue
2625+ if active .status & THREAD_STATUS_HAS_GIL :
2626+ continue
2627+ suspended = self ._find_thread_with_frame (trace , lambda f : f .funcname == "suspended" )
2628+ self .assertIsNotNone (suspended )
2629+ self .assertEqual (suspended .thread_id , active .thread_id )
2630+ self .assertFalse (suspended .status & THREAD_STATUS_ON_CPU )
2631+ break
27012632
27022633 def _run_thread_status_test (self , mode , check_condition ):
27032634 """
0 commit comments