File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -27,6 +27,7 @@ require("./tests/testWebAssembly");
2727require ( "./tests/testEventLoop" ) ;
2828require ( "./tests/testMultithreadedJavascript" ) ;
2929require ( "./tests/testWorkerTerminateDuringLoad" ) ;
30+ require ( "./tests/testWorkerTerminateAfterClose" ) ;
3031require ( "./tests/testWorkerOptions" ) ;
3132require ( "./tests/testWorkerResourceLimits" ) ;
3233require ( "./tests/testInterfaceDefaultMethods" ) ;
Original file line number Diff line number Diff line change 1+ describe ( "Worker terminate after close" , function ( ) {
2+ var SETTLE_AFTER = 300 ;
3+
4+ it ( "stops a worker that keeps running after it called close()" , function ( done ) {
5+ var counter = new Int32Array ( new SharedArrayBuffer ( 4 ) ) ;
6+ var worker = new Worker ( "./workerCloseThenSpinWorker.js" ) ;
7+ worker . postMessage ( counter . buffer ) ;
8+ var started = Date . now ( ) ;
9+
10+ ( function waitForSpin ( ) {
11+ if ( Atomics . load ( counter , 0 ) === 0 ) {
12+ if ( Date . now ( ) - started > 5000 ) {
13+ fail ( "the worker never started running" ) ;
14+ done ( ) ;
15+ return ;
16+ }
17+ setTimeout ( waitForSpin , 20 ) ;
18+ return ;
19+ }
20+ worker . terminate ( ) ;
21+ setTimeout ( function ( ) {
22+ var afterTerminate = Atomics . load ( counter , 0 ) ;
23+ setTimeout ( function ( ) {
24+ expect ( Atomics . load ( counter , 0 ) ) . toBe ( afterTerminate ) ;
25+ done ( ) ;
26+ } , SETTLE_AFTER ) ;
27+ } , SETTLE_AFTER ) ;
28+ } ) ( ) ;
29+ } ) ;
30+ } ) ;
Original file line number Diff line number Diff line change 1+ // close() lets the running callback finish, so this one never returns unless
2+ // terminate() interrupts it.
3+ onmessage = function ( event ) {
4+ var counter = new Int32Array ( event . data ) ;
5+ close ( ) ;
6+ for ( ; ; ) {
7+ Atomics . add ( counter , 0 , 1 ) ;
8+ }
9+ } ;
Original file line number Diff line number Diff line change @@ -142,8 +142,7 @@ void WorkerWrapper::PostMessageToParent(std::shared_ptr<worker::Message> message
142142}
143143
144144void WorkerWrapper::Terminate () {
145- if (isClosing_ || isDisposed_) {
146- // The worker is already shutting down on its own; nothing to do.
145+ if (isDisposed_) {
147146 return ;
148147 }
149148
@@ -160,8 +159,8 @@ void WorkerWrapper::Terminate() {
160159 std::lock_guard<std::mutex> lock (workerIsolateMutex_);
161160 Isolate* isolate = workerIsolate_.load ();
162161 if (isolate != nullptr ) {
163- // The only v8 call that is legal from another thread - interrupts any
164- // JS currently running on the worker (e.g. a busy loop).
162+ // Legal from any thread: interrupts any JS currently running on the
163+ // worker (e.g. a busy loop, including one that follows close() ).
165164 isolate->TerminateExecution ();
166165 // A pump parked with nothing queued runs no JS, so the interrupt
167166 // above never materializes for it - the loop's own flag ends it.
You can’t perform that action at this time.
0 commit comments