From: DongHyun Song Date: Mon, 11 Sep 2023 14:19:55 +0000 (+0900) Subject: Exclusive StartService when 2 apps are racing X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0ddeb76090ba4c11d29c35ab5cd00d343b3bae6b;p=platform%2Fframework%2Fweb%2Fwrtjs.git Exclusive StartService when 2 apps are racing 2 or more service apps are simultaneously running, there have been some race condition issues. - crash, smack error So, it needs to run service apps exclusively on the start() function basis. If previous app's start() is not done yet, then new request app will be defered until done. Change-Id: I6be232cb872e7edb074ffd8c7f1ac5f243333c11 Signed-off-by: DongHyun Song --- diff --git a/wrt_app/service/service_manager.ts b/wrt_app/service/service_manager.ts index 4209af39..37fea323 100644 --- a/wrt_app/service/service_manager.ts +++ b/wrt_app/service/service_manager.ts @@ -11,7 +11,8 @@ interface MessageObserver { } let workers: WorkerMap = {}; -let dyingWorkerQueue: WorkerMap = {}; +let workerStatus: WorkerMap = {}; +let readyWorkers: WorkerMap = {}; let messageObservers: MessageObserver = {}; Object.defineProperty(global, 'serviceType', { @@ -20,25 +21,35 @@ Object.defineProperty(global, 'serviceType', { }); function checkDyingWorker() { - let dyingWorkers = Object.keys(dyingWorkerQueue); - if (dyingWorkers.length) { - let workerId = dyingWorkers[0]; - if (dyingWorkerQueue[workerId] === 'will-terminate') { - dyingWorkerQueue[workerId] = 'terminated'; + for (let workerId in workerStatus) { + if (workerStatus[workerId] === 'will-terminate') { + workerStatus[workerId] = 'terminated'; workers[workerId].terminate(); } } } -function IsDyingWorker(id: string) { - let dyingWorkers = Object.keys(dyingWorkerQueue); - if (dyingWorkers.length && dyingWorkerQueue[id]) { - return ((dyingWorkerQueue[id] === 'will-terminate') || - (dyingWorkerQueue[id] === 'terminated')) +function isDyingWorker(id: string) { + return workerStatus[id] && ((workerStatus[id] === 'will-terminate') || (workerStatus[id] === 'terminated')) +} + +function hasPendingService() { + for (let workerId in workerStatus) { + if (workerStatus[workerId] === 'starting') + return true; } return false; } +function flushFirstReadyWorker() { + let readyWorkerKeys = Object.keys(readyWorkers); + if (!readyWorkerKeys.length) return; + let workerId = readyWorkerKeys[0]; + console.log(`flushFirstReadyWorker : ${workerId}`); + createWorker(readyWorkers[workerId].id, readyWorkers[workerId].startService, readyWorkers[workerId].filename); + delete readyWorkers[workerId]; +} + function createWorker(id: string, startService: string, filename: string) { if (workers[id]) { workers[id].postMessage({ type: 'wake' }); @@ -46,6 +57,14 @@ function createWorker(id: string, startService: string, filename: string) { } wrt.tv?.serviceMount(id); + workerStatus[id] = 'starting'; + setTimeout(() => { + // if worker status doesn't become 'started' within 5s, forcely set it 'started' + if (workerStatus[id] === 'starting') { + workerStatus[id] = 'started'; + flushFirstReadyWorker(); + } + }, 5000); workers[id] = new Worker(startService, { workerData: { id, @@ -54,9 +73,13 @@ function createWorker(id: string, startService: string, filename: string) { }); workers[id].on('message', (message: any) => { switch (message.type) { + case 'started': + workerStatus[id] = 'started'; + flushFirstReadyWorker(); + break; case 'will-terminate': delete messageObservers[id]; - dyingWorkerQueue[id] = 'will-terminate'; + workerStatus[id] = 'will-terminate'; checkDyingWorker(); break; case 'register-message': @@ -71,7 +94,7 @@ function createWorker(id: string, startService: string, filename: string) { }); workers[id].on('exit', (code: number) => { wrt.tv?.serviceUmount(id); - delete dyingWorkerQueue[id]; + delete workerStatus[id]; delete workers[id]; let runningServices = Object.keys(workers); console.debug(`${id} terminated, remain services(${runningServices})`); @@ -95,7 +118,7 @@ let initializeExtensionOnMain = (id: string) => { // same smack label with pid's. // It must be handled ahead of dropThreadPrivilege() // Otherwise, smack violation might hanppen from 'libdbuspolicy'. - global.tizen.systeminfo.getPropertyValue("CPU", () => { }, () => { }); + global.tizen.systeminfo.getPropertyValue('CPU', () => { }, () => { }); if (global['serviceType'] !== 'STANDALONE') { global.tizen.alarm.getAll(); } else { @@ -107,14 +130,18 @@ let initializeExtensionOnMain = (id: string) => { } export function startService(id: string, filename: string) { - if(IsDyingWorker(id)) { + if (isDyingWorker(id)) { console.debug(`startService - ${id} is in stop status, skip start`); return; } console.debug(`startService - ${id}`); initializeExtensionOnMain(id); let startService = `${__dirname}/service_runner.js`; - createWorker(id, startService, filename); + if (!hasPendingService()) { + createWorker(id, startService, filename) + } else { + readyWorkers[id] = { id, startService, filename }; + } } export function stopService(id: string) { diff --git a/wrt_app/service/service_runner.ts b/wrt_app/service/service_runner.ts index ef210c22..35db1a60 100644 --- a/wrt_app/service/service_runner.ts +++ b/wrt_app/service/service_runner.ts @@ -157,7 +157,7 @@ function run() { let filename = workerData.filename; start(id, filename); - + parentPort?.postMessage({ type : 'started' }); parentPort?.on('message', (message) => { console.debug(`Received message type : ${message.type}`); switch (message.type) {