|
10 | 10 | from tests.utils import filter_relevant_allocations
|
11 | 11 |
|
12 | 12 | pytestmark = pytest.mark.skipif(
|
13 |
| - sys.version_info >= (3, 12), reason="Greenlet does not yet support Python 3.12" |
| 13 | + sys.version_info >= (3, 14), reason="Greenlet does not yet support Python 3.14" |
14 | 14 | )
|
15 | 15 |
|
16 | 16 |
|
@@ -194,3 +194,73 @@ def stack(alloc):
|
194 | 194 | assert vallocs[0].tid != vallocs[1].tid != vallocs[6].tid
|
195 | 195 | assert vallocs[0].tid == vallocs[2].tid
|
196 | 196 | assert vallocs[1].tid == vallocs[3].tid == vallocs[4].tid == vallocs[5].tid
|
| 197 | + |
| 198 | + |
| 199 | +def test_uninstall_profile_in_greenlet(tmpdir): |
| 200 | + """Verify that memray handles profile function changes in greenlets correctly.""" |
| 201 | + # GIVEN |
| 202 | + output = Path(tmpdir) / "test.bin" |
| 203 | + subprocess_code = textwrap.dedent( |
| 204 | + f""" |
| 205 | + import greenlet |
| 206 | + import sys |
| 207 | +
|
| 208 | + from memray import Tracker |
| 209 | + from memray._test import MemoryAllocator |
| 210 | +
|
| 211 | + def foo(): |
| 212 | + bar() |
| 213 | + allocator.valloc(1024 * 10) |
| 214 | +
|
| 215 | + def bar(): |
| 216 | + baz() |
| 217 | +
|
| 218 | + def baz(): |
| 219 | + sys.setprofile(None) |
| 220 | + other.switch() |
| 221 | +
|
| 222 | + def test(): |
| 223 | + allocator.valloc(1024 * 70) |
| 224 | + main_greenlet.switch() |
| 225 | +
|
| 226 | +
|
| 227 | + allocator = MemoryAllocator() |
| 228 | + output = "{output}" |
| 229 | +
|
| 230 | + with Tracker(output): |
| 231 | + main_greenlet = greenlet.getcurrent() |
| 232 | + other = greenlet.greenlet(test) |
| 233 | + foo() |
| 234 | +
|
| 235 | + """ |
| 236 | + ) |
| 237 | + |
| 238 | + # WHEN |
| 239 | + subprocess.run([sys.executable, "-Xdev", "-c", subprocess_code], timeout=5) |
| 240 | + |
| 241 | + # THEN |
| 242 | + reader = FileReader(output) |
| 243 | + records = list(reader.get_allocation_records()) |
| 244 | + vallocs = [ |
| 245 | + record |
| 246 | + for record in filter_relevant_allocations(records) |
| 247 | + if record.allocator == AllocatorType.VALLOC |
| 248 | + ] |
| 249 | + |
| 250 | + def stack(alloc): |
| 251 | + return [frame[0] for frame in alloc.stack_trace()] |
| 252 | + |
| 253 | + # Verify allocations and their stack traces (which should be empty |
| 254 | + # because we remove the tracking function) |
| 255 | + assert len(vallocs) == 2 |
| 256 | + |
| 257 | + assert stack(vallocs[0]) == [] |
| 258 | + assert vallocs[0].size == 70 * 1024 |
| 259 | + |
| 260 | + assert stack(vallocs[1]) == [] |
| 261 | + assert vallocs[1].size == 10 * 1024 |
| 262 | + |
| 263 | + # Verify thread IDs |
| 264 | + main_tid = vallocs[0].tid # inner greenlet |
| 265 | + outer_tid = vallocs[1].tid # outer greenlet |
| 266 | + assert main_tid == outer_tid |
0 commit comments