From 5fcb8a5f26b570169c30dac98ba158a2763b0005 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Mon, 11 Sep 2023 23:19:55 +0900 Subject: [PATCH] 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 --- wrt_app/service/service_manager.ts | 59 ++++++++++++++++++++++-------- wrt_app/service/service_runner.ts | 2 +- 2 files changed, 44 insertions(+), 17 deletions(-) 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) { -- 2.34.1