Skip to content

Commit cb8beec

Browse files
committed
fix(scanner): workers not always terminated
The computed property `shouldScan` in QrcodeStream is the source of truth for the scanners state. Therefore each `keepScanning` call receives a function enabling it to check `shouldScan`s value outside of the components context. Since computed properties are evaluated in an asynchronous manner, a running scanner might miss point where `shouldScan` is actually `false`. When `keepScanning` is called many times in a row, new web workers are spawned endlessly without being terminated, causing a major memory leak. Now fixed by putting the action to terminate scanners in the same watcher where scanners are started.
1 parent 506de1a commit cb8beec

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

src/components/QrcodeStream.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export default {
6464
cameraInstance: null,
6565
destroyed: false,
6666
constraints: {},
67+
stopScanning: () => {},
6768
}
6869
},
6970
@@ -118,6 +119,8 @@ export default {
118119
this.clearPauseFrame()
119120
this.clearTrackingLayer()
120121
this.startScanning()
122+
} else {
123+
this.stopScanning()
121124
}
122125
},
123126
@@ -186,16 +189,17 @@ export default {
186189
},
187190
188191
startScanning () {
192+
// this.stopScanning()
193+
189194
const detectHandler = result => {
190195
this.onDetect(
191196
Promise.resolve({ source: 'stream', ...result })
192197
)
193198
}
194199
195-
keepScanning(this.cameraInstance, {
200+
this.stopScanning = keepScanning(this.cameraInstance, {
196201
detectHandler,
197202
locateHandler: this.onLocate,
198-
shouldContinue: () => this.shouldScan,
199203
minDelay: this.scanInterval,
200204
})
201205
},

src/misc/scanner.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export function keepScanning (camera, options) {
2323
const {
2424
detectHandler,
2525
locateHandler,
26-
shouldContinue,
2726
minDelay,
2827
} = options
2928

@@ -36,6 +35,7 @@ export function keepScanning (camera, options) {
3635
// If worker can't process frames fast enough, memory will quickly full up.
3736
// Make sure to process only one frame at a time.
3837
let workerBusy = false
38+
let shouldContinue = true
3939

4040
worker.onmessage = event => {
4141
workerBusy = false
@@ -55,7 +55,7 @@ export function keepScanning (camera, options) {
5555
}
5656

5757
const processFrame = timeNow => {
58-
if (shouldContinue()) {
58+
if (shouldContinue) {
5959
window.requestAnimationFrame(processFrame)
6060

6161
if (timeNow - lastScanned >= minDelay) {
@@ -75,4 +75,8 @@ export function keepScanning (camera, options) {
7575
}
7676

7777
processFrame()
78+
79+
return () => {
80+
shouldContinue = false
81+
}
7882
}

0 commit comments

Comments
 (0)