1 import { Worker, isMainThread } from 'worker_threads';
2 import { wrt } from '../browser/wrt';
3 import * as XWalkExtension from '../common/wrt_xwalk_extension';
8 let workers: WorkerMap = {};
9 let dyingWorkerQueue: WorkerMap = {};
11 Object.defineProperty(global, 'serviceType', {
12 value: wrt.getServiceModel(),
16 function checkDyingWorker() {
17 let dyingWorkers = Object.keys(dyingWorkerQueue);
18 if (dyingWorkers.length) {
19 let workerId = dyingWorkers[0];
20 if (dyingWorkerQueue[workerId] === 'will-terminate') {
21 dyingWorkerQueue[workerId] = 'terminated';
22 workers[workerId].terminate();
27 function IsDyingWorker(id: string) {
28 let dyingWorkers = Object.keys(dyingWorkerQueue);
29 if (dyingWorkers.length && dyingWorkerQueue[id]) {
30 return ((dyingWorkerQueue[id] === 'will-terminate') ||
31 (dyingWorkerQueue[id] === 'terminated'))
36 function createWorker(id: string, startService: string, filename: string) {
38 workers[id].postMessage({ type: 'wake' });
42 wrt.tv?.serviceMount(id);
43 workers[id] = new Worker(startService, {
49 workers[id].on('message', (message: string) => {
50 if (message === 'will-terminate') {
51 dyingWorkerQueue[id] = message;
55 workers[id].on('exit', (code: number) => {
56 wrt.tv?.serviceUmount(id);
57 delete dyingWorkerQueue[id];
59 let runningServices = Object.keys(workers);
60 console.debug(`${id} terminated, remain services(${runningServices})`);
65 function terminateWorker(id: string, delay: number) {
67 console.debug(`This worker is already terminated. ${id}`);
70 console.debug(`${id} will shutdown after ${delay}ms`);
71 workers[id].postMessage({ type: 'stop', delay });
74 let initializeExtensionOnMain = () => {
75 initializeExtensionOnMain = () => {};
76 XWalkExtension.initialize();
77 // This is workaround solution to make webapis's singleton worker, which has
78 // same smack label with pid's.
79 // It must be handled ahead of dropThreadPrivilege()
80 // Otherwise, smack violation might hanppen from 'libdbuspolicy'.
81 global.tizen.systeminfo.getPropertyValue("CPU", () => { }, () => { });
84 export function startService(id: string, filename: string) {
85 if(IsDyingWorker(id)) {
86 console.debug(`startService - ${id} is in stop status, skip start`);
89 console.debug(`startService - ${id}`);
90 initializeExtensionOnMain();
91 if (global['serviceType'] === 'STANDALONE') {
92 let ids = id.split(':');
93 let serviceId = ids[0];
94 let packageId = serviceId.split('.')[0];
95 wrt.security?.dropThreadPrivilege(packageId, serviceId);
97 let startService = `${__dirname}/service_runner.js`;
98 createWorker(id, startService, filename);
101 export function stopService(id: string) {
102 console.debug(`stopService - ${id}`);
103 terminateWorker(id, 500);
106 export function handleBuiltinService(serviceId: string, serviceName: string) {
110 let need_stop = (serviceName.substr(0, 5) === 'stop_');
112 console.debug(`${serviceName} will be terminated.`);
113 workers[serviceId].terminate();
115 console.debug(`Builtin service is ${serviceName}`);
116 let startService = `${__dirname}/../service/builtins/${serviceName}.js`;
117 createWorker(serviceId, startService, '');