GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — fix(worker): keep the worker isolate alive while terminate() uses it, and let it stop a closing worker by adrian-niculescu · Pull Request #2067 · NativeScript/android

Conversation

@adrian-niculescu

@adrian-niculescu adrian-niculescu commented Oct 6, 2026 •
edited by coderabbitai Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Calling terminate() on a Worker that is ending on its own at the same moment, for example through its own close(), can make the parent thread interrupt the worker's isolate after the worker thread has already disposed it. A parent that terminates its child workers during its own shutdown races the same way. Separately, terminate() cannot stop a worker that called close() and kept running, so close(); while (true) {} spins forever.

WorkerWrapper::Terminate reads workerIsolate_ and then calls TerminateExecution() and the event-loop lookup on it with no lock, while BackgroundLooper clears the pointer and disposes the isolate during teardown. Nothing makes the worker thread wait for a Terminate that has already read the pointer. Terminate now holds a mutex across the read and the use, and the worker thread takes the same mutex when it clears the pointer, before disposing the isolate: a terminate that already read it finishes with it first, and a later one finds null. This is the same fix as NativeScript/ios#478 on iOS.

close() only ends the worker once its running callback returns, and Terminate returned early for a closing worker. It no longer returns early for a closing worker, which matches the iOS runtime, so it interrupts one that is still running.

The isolate race window is a few instructions wide, so it has no spec. With a sleep injected between the read and the use, a worker that closes itself while terminate() runs is already disposed when the parent touches its isolate on main, and stays alive until the parent is done with this change. The new spec for a worker spinning after close() fails on main and passes here, and the full device suite passes.

Summary by CodeRabbit

  • Bug Fixes
    • Workers that have called close() but continue running can now be terminated reliably. Their ongoing activity stops after termination is requested.
  • Tests
    • Added coverage verifying that termination stops a closing worker’s ongoing activity. The test checks that its shared counter remains unchanged after termination.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@adrian-niculescu
fix(worker): keep the worker isolate alive while terminate() uses it
a9a5ea4
Terminate() read the worker isolate and then interrupted it with no lock, while the worker thread could clear the pointer and dispose that isolate in the same window: a worker that ends through its own close() while its parent calls terminate(), or a parent that terminates its children during its own shutdown. Terminate() now holds a mutex across the read and the use, and the worker thread takes it when it withdraws the isolate, before disposing it.
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Worker termination can now proceed after a worker calls close(), with isolate access synchronized against shutdown. The app test suite adds a worker test that checks whether termination stops shared-counter increments.

Changes: Worker termination after close

Layer / File(s) Summary
Synchronize termination and isolate shutdown
test-app/runtime/src/main/cpp/WorkerWrapper.h, test-app/runtime/src/main/cpp/WorkerWrapper.cpp
Terminate proceeds unless the worker is disposed and holds workerIsolateMutex_ while using the isolate. Shutdown uses the same mutex when clearing the isolate pointer.
Test termination after close
test-app/app/src/main/assets/app/tests/workerCloseThenSpinWorker.js, test-app/app/src/main/assets/app/tests/testWorkerTerminateAfterClose.js, test-app/app/src/main/assets/app/mainpage.js
The worker calls close() and increments a shared counter until signaled to stop. The test terminates the worker after observing increments and checks that the counter remains unchanged. The app loads the test module.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Possibly related PRs

  • NativeScript/android#2044: Changes the worker termination and shutdown sequence in WorkerWrapper.cpp, including when the worker root and registry entry are cleared.

Suggested reviewers: edusperoni

Merge Risk: Minimal · up to 7e3a4

This change synchronizes worker termination with isolate shutdown and lets terminate() stop a worker that has called close(). A regression test accompanies it. No actionable merge-blocking risk remains.

Pre-merge checks: Passed 4

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title names the two changes in the PR: keeping the worker isolate alive while terminate() uses it, and allowing terminate() to stop a worker that called close(). The raw summary confirms both: the…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the two changes in the PR: keeping the worker isolate alive while terminate() uses it, and allowing terminate() to stop a worker that called close(). The raw summary confirms both: the WorkerWrapper mutex guards isolate use and teardown, and the early return for closing workers is removed. The title is long at 102 characters, but it is specific and accurate.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

  • X
  • Mastodon
  • Reddit
  • LinkedIn
Recent review info

Run configuration

  • Source mode: Auto
  • Repository: NativeScript/android
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 560b3bf
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c5479350-f555-43ca-8d83-39cc9e891045
Commits

Reviewing files that changed from the base of the PR and between 44f3c8c and 7e3a456.

Files selected for processing: 3

  • test-app/app/src/main/assets/app/mainpage.js
  • test-app/runtime/src/main/cpp/WorkerWrapper.cpp
  • test-app/runtime/src/main/cpp/WorkerWrapper.h

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@adrian-niculescu
fix(worker): let terminate() stop a worker that called close()
921209f
close() only ends the worker once its running callback returns, and terminate() returned early for a closing worker, so a worker that kept running after close() could not be stopped. terminate() now interrupts it like any other running worker.
@adrian-niculescu adrian-niculescu changed the title fix(worker): keep the worker isolate alive while terminate() uses it fix(worker): keep the worker isolate alive while terminate() uses it, and let it stop a closing worker Oct 6, 2026
@adrian-niculescu
test(worker): stop the close-then-spin worker on cleanup and fit the …
44f3c8c
…spec in its timeout

A run where terminate() failed left the worker spinning past the spec. The loop now also checks a stop flag the spec raises in afterEach, the spec gets its own Jasmine timeout with a shorter start deadline, and the start-deadline branch fails through an expectation rather than the fail() global this Jasmine does not provide.
@adrian-niculescu
adrian-niculescu marked this pull request as ready for review October 6, 2026 21:52
@adrian-niculescu adrian-niculescu mentioned this pull request Oct 6, 2026
fix(worker): leave the inspector pause loop when the worker is terminating #2071
Open
@edusperoni
Merge branch 'main' into fix/worker-terminate-isolate-race
7e3a456
@edusperoni edusperoni mentioned this pull request Nov 11, 2026
ci: keep crash diagnostics when the test app dies or hangs #2109
Merged
edusperoni
edusperoni approved these changes Nov 11, 2026
View reviewed changes

@edusperoni edusperoni left a comment

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed and verified: merged with current main, full device suite passes on main + #2067 + #2070 + #2069 (1545 specs, 0 failures, 3 runs). The earlier CI Test failure did not reproduce on rerun.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@edusperoni
edusperoni merged commit 602e8ab into NativeScript:main Nov 11, 2026
5 of 6 checks passed

Uh oh!

There was an error while loading. Please reload this page.

This was referenced Nov 11, 2026
fix(worker): let a heap-limit terminate re-enter the inspector lock from console.log #2070
Merged
fix(worker): tear down a worker runtime whose Java bootstrap failed #2069
Merged
fix(worker): drop callbacks from closing workers #2108
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@edusperoni edusperoni edusperoni approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@adrian-niculescu @edusperoni
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.