Repository navigation
Conversation
When there is no Application yet, perform() waits for a hook on handleBindApplication() or getPackageInfo(). An attach that lands after the app made both calls, but before it set its Application, never sees either hook fire, so the callback never runs. Also check currentApplication() every 50 ms, until it returns an Application or a hook fires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Java.perform()can wait forever when Frida attaches to an app that is still starting.Cause
When there is no
Applicationyet,perform()queues the callback, and_performPendingVmOpsWhenReady()decides when to run it:ActivityThread.currentApplication()once.handleBindApplication()andgetPackageInfo(), and runs the queue from whichever is called first.handleBindApplication()callsgetPackageInfo()early, and only later sets theApplicationthatcurrentApplication()returns. An attach that lands between the two sees null in step 1, then hooks two methods that have already run. Neither runs again, so the callback never runs and no error is reported.We hit this when attaching to apps right after starting them.
Change
After it installs the hooks,
_performPendingVmOpsWhenReady()also checkscurrentApplication()every 50 ms, until it returns anApplicationor a hook fires. The existinginitializedflag makes sure the queue runs once, whichever path gets there first.Test
PerformTest.performRunsWhenNoHookFirescovers it. The test runner is not an app process, so the test:Java._cachedIsAppProcess, soperform()takes the app path;ActivityThread.currentApplication(), so it returns null until 100 ms afterperform(), then a stand-inApplication.Nothing in the runner calls the two hooked methods. That is the same state as an attach that came too late for them. Without the fix,
getNextMessage()gives up after 5 s and the test fails.I could not run the suite:
tests.ymlfails onmaintoday (59 of 64 tests failed on API 29 x86_64 in the latest push run, because the scripts send nothing back), and I don't have the NDK setup for the native runner. Instead I ran the test's steps as a script in a real app, on an Android 16 x86_64 emulator with Frida 17.19.0, 5 rounds each:currentApplication()null for 100 msperform()ranThe one run without the fix that passed was the first, while the app was still starting, so a later
getPackageInfo()call probably fired the hook.Note
In a process that never gets an
Application, the check keeps running every 50 ms.perform()already waited forever there; only the timer is new.🤖 Generated with Claude Code