Skip to content

Commit 6d364ca

Browse files
committed
Also track handles' stack
It is useful to be able to know where handles were created.
1 parent aaec3c0 commit 6d364ca

File tree

1 file changed

+21
-10
lines changed

1 file changed

+21
-10
lines changed

src/payloads/dump_heap.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def __payload_entrypoint(output_path: str) -> None:
88
import sys
99
from typing import Any
1010

11-
MAX_PAYLOAD_SIZE = 128
11+
DEFAULT_MAX_PAYLOAD_SIZE = 128
1212

1313
logging.warning("XXX: dump_heap: writing report to %r", output_path)
1414
logging.warning("XXX: dump_heap: collecting gc")
@@ -179,40 +179,51 @@ def _get_payload(obj: Any) -> bytes | None:
179179
try:
180180
payload_str: str | None = None
181181
payload: bytes | None = None
182+
max_payload_size = DEFAULT_MAX_PAYLOAD_SIZE
182183
if isinstance(obj, str):
183184
payload_str = obj
184185
elif isinstance(obj, dict):
185186
payload_entries: list[bytes] = []
186187
payload_length = 0
187188
for key in obj.keys():
188189
if isinstance(key, bytes):
189-
if len(key) > MAX_PAYLOAD_SIZE:
190-
key_bytes = key[:MAX_PAYLOAD_SIZE]
190+
if len(key) > max_payload_size:
191+
key_bytes = key[:max_payload_size]
191192
else:
192193
key_bytes = key
193194
elif isinstance(key, str):
194-
if len(key) > MAX_PAYLOAD_SIZE:
195-
key_bytes = key[:MAX_PAYLOAD_SIZE].encode(
195+
if len(key) > max_payload_size:
196+
key_bytes = key[:max_payload_size].encode(
196197
"utf-8", "replace"
197198
)
198199
else:
199200
key_bytes = key.encode("utf-8", "replace")
200201
else:
201202
key_str = str(key)
202-
if len(key_str) > MAX_PAYLOAD_SIZE:
203-
key_bytes = key_str[:MAX_PAYLOAD_SIZE].encode(
203+
if len(key_str) > max_payload_size:
204+
key_bytes = key_str[:max_payload_size].encode(
204205
"utf-8", "replace"
205206
)
206207
else:
207208
key_bytes = key_str.encode("utf-8", "replace")
208209
payload_entries.append(key_bytes)
209210
payload_length += len(key_bytes) + 1
210-
if payload_length > MAX_PAYLOAD_SIZE:
211+
if payload_length > max_payload_size:
211212
break
212213
payload = b",".join(payload_entries)
213214
del payload_entries
214215
elif isinstance(obj, asyncio.Task):
215216
payload_str = obj.get_name()
217+
elif isinstance(obj, asyncio.events.Handle):
218+
max_payload_size = 4096
219+
# The important bits in the stack frames are always towards at
220+
# the bottom. So we revert it for simplicity.
221+
source_traceback = obj._source_traceback # type: ignore[attr-defined]
222+
payload_str = (
223+
"\n".join(repr(frame) for frame in source_traceback[::-1])
224+
if source_traceback
225+
else repr(obj)
226+
)
216227
elif inspect.ismodule(obj):
217228
payload_str = obj.__name__
218229
elif inspect.isclass(obj):
@@ -226,10 +237,10 @@ def _get_payload(obj: Any) -> bytes | None:
226237
payload_str = obj.__qualname__
227238

228239
if payload is None and payload_str is not None:
229-
if len(payload_str) <= MAX_PAYLOAD_SIZE:
240+
if len(payload_str) <= max_payload_size:
230241
payload = payload_str.encode("utf-8", "replace")
231242
else:
232-
payload = payload_str[:MAX_PAYLOAD_SIZE].encode("utf-8", "replace")
243+
payload = payload_str[:max_payload_size].encode("utf-8", "replace")
233244
del payload_str
234245
except: # noqa: E722
235246
pass

0 commit comments

Comments
 (0)