(self)
| 965 | |
| 966 | @cpython_only |
| 967 | def test_frame_tstate_tracing(self): |
| 968 | _testcapi = import_module("_testcapi") |
| 969 | # Issue #14432: Crash when a generator is created in a C thread that is |
| 970 | # destroyed while the generator is still used. The issue was that a |
| 971 | # generator contains a frame, and the frame kept a reference to the |
| 972 | # Python state of the destroyed C thread. The crash occurs when a trace |
| 973 | # function is setup. |
| 974 | |
| 975 | def noop_trace(frame, event, arg): |
| 976 | # no operation |
| 977 | return noop_trace |
| 978 | |
| 979 | def generator(): |
| 980 | while 1: |
| 981 | yield "generator" |
| 982 | |
| 983 | def callback(): |
| 984 | if callback.gen is None: |
| 985 | callback.gen = generator() |
| 986 | return next(callback.gen) |
| 987 | callback.gen = None |
| 988 | |
| 989 | old_trace = sys.gettrace() |
| 990 | sys.settrace(noop_trace) |
| 991 | try: |
| 992 | # Install a trace function |
| 993 | threading.settrace(noop_trace) |
| 994 | |
| 995 | # Create a generator in a C thread which exits after the call |
| 996 | _testcapi.call_in_temporary_c_thread(callback) |
| 997 | |
| 998 | # Call the generator in a different Python thread, check that the |
| 999 | # generator didn't keep a reference to the destroyed thread state |
| 1000 | for test in range(3): |
| 1001 | # The trace function is still called here |
| 1002 | callback() |
| 1003 | finally: |
| 1004 | sys.settrace(old_trace) |
| 1005 | threading.settrace(old_trace) |
| 1006 | |
| 1007 | def test_gettrace(self): |
| 1008 | def noop_trace(frame, event, arg): |
nothing calls this directly
no test coverage detected