Skip to content

tracer: Fix MemoryRepository and messages arriving after stop() - #209

Open
arxhr007 wants to merge 1 commit into
frida:mainfrom
arxhr007:fix/150-tracer-stop
Open

arxhr007 wants to merge 1 commit into
frida:mainfrom
arxhr007:fix/150-tracer-stop

Conversation

@arxhr007

Copy link
Copy Markdown

Fixes #150

Running tests/test_tracer.py could print a traceback from the reactor thread while still reporting OK. On current main there are two bugs on that path:

  1. MemoryRepository used TraceTarget as a dict key. TraceTarget has been an unhashable dataclass since 5a5cdc8 ("tracer: Add a basic web UI"), so every handlers:get request through MemoryRepository raised TypeError: unhashable type: 'TraceTarget'. It now keys by target.identifier, like FileRepository does.
  2. Messages handled after stop(). A message queued on the reactor before stop() could be handled after it, reaching self._script.post() with _script already None. That is the AttributeError from the issue. _on_message now ignores messages once the tracer has stopped, since there is no script left to reply to.

Both exceptions happen on the reactor thread, so test_basics never failed. It now fails if a reactor thread raises. That check is timing dependent, so two new tests cover both cases deterministically, without a target process.

Test results

The new tests were written before the fixes:

Code Result
main TypeError: unhashable type: 'TraceTarget' in the new tests
fix 1 only test_message_after_stop_is_ignored: AttributeError: 'NoneType' object has no attribute 'post'
both fixes all 7 tests in tests/test_tracer.py pass, test_basics clean on 10 repeated runs

The whole tests/ directory passes: 35 tests, 33 before plus the 2 new ones. black and isort pass.

frida-trace -i 'open*' -f /bin/cat -- /etc/hostname /etc/os-release traces the same two open() calls with and without this change. FileRepository is not touched.

Tested on Ubuntu 24.04 (WSL2), Python 3.12, frida 17.24.3. The agent and UI were taken from the frida-tools 14.11.0 wheel rather than built from source.

Not changed here: an exception other than OperationCancelledError in a scheduled task still ends Reactor._run, which is how these errors stopped the worker thread.

The code was written with AI assistance.

MemoryRepository keyed its handlers by TraceTarget, which has been
unhashable since it became a dataclass in 5a5cdc8 ("tracer: Add a basic
web UI"), so every handlers:get request raised a TypeError.

A message queued on the reactor before stop() but handled after it then
reached self._script.post() with _script already set to None, which is
the AttributeError reported in frida#150.

Both exceptions are raised on the reactor thread, so test_basics kept
passing. It now fails when a reactor thread raises, and two new tests
cover both cases without needing a target process.

Fixes frida#150
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test_tracer.py test_basics prints stack trace

1 participant