Skip to content

Restart a plugin whose closed sessions stay stuck in native code - #12

Merged
naijun0403 merged 1 commit into
masterfrom
fix/stuck-engine-threads
Oct 4, 2026
Merged

naijun0403 merged 1 commit into
masterfrom
fix/stuck-engine-threads

Conversation

@naijun0403

Copy link
Copy Markdown
Member

Summary

A script blocked in native code, such as Node's execSync, Atomics.wait or a JNI call that never returns, does not notice ScriptEngine.interrupt(). When the host gives up on it and closes the session, EngineEndpoint.close() interrupts and shuts the engine thread down. That thread keeps running, with its whole JavaScript heap, until the process ends. Every such event leaks one more, and in a plugin several projects share they pile up until the process runs out of memory and takes every project down at once.

PluginService now checks each closed session 10 s after closing it:

  • if its thread has stopped (the new isStopped on EngineEndpoint and ProviderEndpoint, backed by EngineThread.isTerminated), nothing happens;
  • otherwise the session counts as stuck and is logged. Sessions that finished in the meantime are dropped from the count.
  • With no session open, nothing is lost by ending the process, so it ends at once. With others open, it waits until 3 are stuck, then ends anyway, because only a new process frees them.

Ending the process is how the host already recovers from a crashed plugin. Since MessengerBotR#275 and #11 it fails what waited at once, counts the crash once for its backoff, and reloads the projects that still use the plugin about 5 s later.

stuckAfterMs and restartProcess are internal, so the tests can shorten the wait and observe the restart instead of ending the test process. Additions only: EngineThread.isTerminated and the two isStopped properties. No wire, protocol or Binder change.

Testing

  • New Robolectric tests in PluginServiceTest:
    • a stuck session with nothing else open restarts the plugin;
    • a stuck session waits while another session is open;
    • a session that stops is not counted.
  • ./gradlew :contract:test :android:testDebugUnitTest :tck:test :android:assembleRelease: 98 tests pass. The android suite passed 3 runs in a row.

After this is merged I will bump the submodule in MessengerBotR, NodeJSPlugin and PluginFixtures.

@naijun0403
naijun0403 merged commit adfc735 into master Oct 4, 2026
1 check passed
@naijun0403
naijun0403 deleted the fix/stuck-engine-threads branch October 4, 2026 09:30
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.

1 participant