(self)
| 1012 | |
| 1013 | @cpython_only |
| 1014 | def test_frame_tstate_tracing(self): |
| 1015 | _testcapi = import_module("_testcapi") |
| 1016 | # Issue #14432: Crash when a generator is created in a C thread that is |
| 1017 | # destroyed while the generator is still used. The issue was that a |
| 1018 | # generator contains a frame, and the frame kept a reference to the |
| 1019 | # Python state of the destroyed C thread. The crash occurs when a trace |
| 1020 | # function is setup. |
| 1021 | |
| 1022 | def noop_trace(frame, event, arg): |
| 1023 | # no operation |
| 1024 | return noop_trace |
| 1025 | |
| 1026 | def generator(): |
| 1027 | while 1: |
| 1028 | yield "generator" |
| 1029 | |
| 1030 | def callback(): |
| 1031 | if callback.gen is None: |
| 1032 | callback.gen = generator() |
| 1033 | return next(callback.gen) |
| 1034 | callback.gen = None |
| 1035 | |
| 1036 | old_trace = sys.gettrace() |
| 1037 | sys.settrace(noop_trace) |
| 1038 | try: |
| 1039 | # Install a trace function |
| 1040 | threading.settrace(noop_trace) |
| 1041 | |
| 1042 | # Create a generator in a C thread which exits after the call |
| 1043 | _testcapi.call_in_temporary_c_thread(callback) |
| 1044 | |
| 1045 | # Call the generator in a different Python thread, check that the |
| 1046 | # generator didn't keep a reference to the destroyed thread state |
| 1047 | for test in range(3): |
| 1048 | # The trace function is still called here |
| 1049 | callback() |
| 1050 | finally: |
| 1051 | sys.settrace(old_trace) |
| 1052 | threading.settrace(old_trace) |
| 1053 | |
| 1054 | def test_gettrace(self): |
| 1055 | def noop_trace(frame, event, arg): |
nothing calls this directly
no test coverage detected