Skip to content

Commit f76808a

Browse files
committed
fix: workers should gracefully shutdown on close()
1 parent fb0a5f4 commit f76808a

4 files changed

Lines changed: 45 additions & 10 deletions

File tree

NativeScript/runtime/ConcurrentQueue.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,19 @@ void ConcurrentQueue::SignalAndWakeUp() {
5454
void ConcurrentQueue::Terminate() {
5555
std::unique_lock<std::mutex> lock(initializationMutex_);
5656
terminated = true;
57-
if (this->runLoop_) {
58-
CFRunLoopStop(this->runLoop_);
57+
CFRunLoopRef runLoop = this->runLoop_;
58+
CFRunLoopSourceRef source = this->runLoopTasksSource_;
59+
this->runLoopTasksSource_ = nullptr;
60+
this->runLoop_ = nullptr;
61+
62+
if (runLoop) {
63+
CFRunLoopStop(runLoop);
5964
}
6065

61-
if (this->runLoopTasksSource_) {
62-
CFRunLoopRemoveSource(this->runLoop_, this->runLoopTasksSource_, kCFRunLoopCommonModes);
63-
CFRunLoopSourceInvalidate(this->runLoopTasksSource_);
64-
CFRelease(this->runLoopTasksSource_);
66+
if (source) {
67+
CFRunLoopRemoveSource(runLoop, source, kCFRunLoopCommonModes);
68+
CFRunLoopSourceInvalidate(source);
69+
CFRelease(source);
6570
}
6671
}
6772

NativeScript/runtime/DataWrapper.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,8 +690,8 @@ class WorkerWrapper: public BaseDataWrapper {
690690
private:
691691
v8::Isolate* mainIsolate_;
692692
v8::Isolate* workerIsolate_;
693-
bool isRunning_;
694-
bool isClosing_;
693+
std::atomic<bool> isRunning_;
694+
std::atomic<bool> isClosing_;
695695
std::atomic<bool> isTerminating_;
696696
bool isDisposed_;
697697
bool isWeak_;

NativeScript/runtime/WorkerWrapper.mm

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
const int WorkerWrapper::WorkerId() { return this->workerId_; }
4141

4242
void WorkerWrapper::PostMessage(std::shared_ptr<worker::Message> message) {
43-
if (!this->isTerminating_) {
43+
if (!this->isTerminating_ && !this->isClosing_) {
4444
this->queue_.Push(message);
4545
}
4646
}
@@ -66,7 +66,7 @@
6666
Local<Object> global = context->Global();
6767

6868
for (std::shared_ptr<worker::Message> message : messages) {
69-
if (this->isTerminating_) {
69+
if (this->isTerminating_ || this->isClosing_) {
7070
break;
7171
}
7272
TryCatch tc(this->workerIsolate_);
@@ -76,6 +76,14 @@
7676
this->CallOnErrorHandlers(tc);
7777
}
7878
}
79+
80+
if (this->isClosing_) {
81+
bool wasTerminating = this->isTerminating_.exchange(true);
82+
if (!wasTerminating) {
83+
this->queue_.Terminate();
84+
this->isRunning_ = false;
85+
}
86+
}
7987
}
8088

8189
void WorkerWrapper::BackgroundLooper(std::function<Isolate*()> func) {

TestRunner/app/tests/shared/Workers/index.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,28 @@ describe("TNS Workers", () => {
381381
}, DEFAULT_TIMEOUT_BEFORE_ASSERT);
382382
});
383383

384+
it("Worker should fully shut down after close() without needing terminate()", (done) => {
385+
var worker = new Worker("./tests/shared/Workers/EvalWorker.js");
386+
387+
worker.postMessage({
388+
eval: "close(); postMessage('closing');"
389+
});
390+
391+
var responseCounter = 0;
392+
worker.onmessage = (msg) => {
393+
responseCounter++;
394+
};
395+
396+
setTimeout(() => {
397+
worker.postMessage({ eval: "postMessage('should not arrive');" });
398+
}, 500);
399+
400+
setTimeout(() => {
401+
expect(responseCounter).toBe(1);
402+
done();
403+
}, DEFAULT_TIMEOUT_BEFORE_ASSERT + 1000);
404+
});
405+
384406
it("Test onerror invoked for a script that has invalid syntax", (done) => {
385407
var worker = new Worker("./tests/shared/Workers/WorkerInvalidSyntax.js");
386408

0 commit comments

Comments
 (0)