}
let workers: WorkerMap = {};
-let dyingWorkerQueue: WorkerMap = {};
+let workerStatus: WorkerMap = {};
+let readyWorkers: WorkerMap = {};
let messageObservers: MessageObserver = {};
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' });
}
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,
});
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':
});
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})`);
// 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 {
}
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) {