[Service] Call destroy() of FunctionTemplate 85/265085/5
authorDongHyun Song <dh81.song@samsung.com>
Fri, 15 Oct 2021 02:43:26 +0000 (11:43 +0900)
committerDongHyun Song <dh81.song@samsung.com>
Fri, 15 Oct 2021 04:42:31 +0000 (13:42 +0900)
FunctionTemplate(prototype) remains memory leak even though node
worker isolate is gone.

This patch calls destroy() of prototype explicitly, which is made
by gin_helper::ObjectTemplateBuilder()
 - wrt, wrt.tv, wrt.mde, wrt.security, wrt.edge, xwalk

Related patch:
https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/264969/

Change-Id: I0cfea24bd0bcec64012f493e3e8bca565fc4f073
Signed-off-by: DongHyun Song <dh81.song@samsung.com>
wrt_app/common/wrt_xwalk_extension.ts
wrt_app/service/device_api_router.ts
wrt_app/service/service_runner.ts

index 4e32394f83512aaee024a735f59bef774cf3360b..9ea29f452a15a97871599178b6f6df61dbb93c6d 100644 (file)
@@ -26,13 +26,14 @@ let extensions_: { [key: string]: NativeXWalkExtension } = {};
 global.window = global.window ?? global;
 
 class XWalkExtension {
+  extensions: NativeXWalkExtension[] =
+      process.wrtBinding('wrt_xwalk_extension').getExtensions();
+
   constructor() {
-    const binding: NativeWRTjs.XWalkExtensionBinding = process.wrtBinding('wrt_xwalk_extension')
-    var extensions: NativeXWalkExtension[] = binding.getExtensions();
-    for (var i = 0; i < extensions.length; i++) {
-      extensions[i].loaded = false;
-      console.debug("Load extension : " + extensions[i].name);
-      extensions_[extensions[i].name] = extensions[i];
+    for (var i = 0; i < this.extensions.length; i++) {
+      this.extensions[i].loaded = false;
+      console.debug("Load extension : " + this.extensions[i].name);
+      extensions_[this.extensions[i].name] = this.extensions[i];
     }
     for (var name in extensions_) {
       if (!extensions_[name].use_trampoline) {
@@ -218,6 +219,11 @@ class XWalkExtension {
       delete global[parent_name][base_name];
     }
   }
+
+  destory() {
+    for (var i = 0; i < this.extensions.length; i++)
+      this.extensions[i].destroy();
+  }
 }
 
 export const initialize = () => {
@@ -230,6 +236,7 @@ export const setRuntimeMessageHandler = (handler: (type: string, data?: string,
 }
 
 export let cleanup = () => {
+  instance?.destory();
   delete global.tizen;
   instance = undefined;
 }
index 98cbe038c975262e21d5b1444589003fed5326d3..955fc7d15d9fe9c99af5594ac6078136727a57e1 100644 (file)
@@ -349,3 +349,13 @@ export class DeviceAPIRouter {
     }
   }
 }
+
+let instance: DeviceAPIRouter | undefined;
+export const initialize = (id: string, isGlobal: boolean) => {
+  instance = new DeviceAPIRouter(id, isGlobal);
+}
+
+export const cleanup = () => {
+  delete global.webapis;
+  instance = undefined;
+}
\ No newline at end of file
index d110017a42dffe41bdf7e99900f9b86c7e1082f6..d3a47f3efef7341ac2ba70b5483fc8068be4cc39 100644 (file)
@@ -1,14 +1,9 @@
 import '../common/init';
 import * as XWalkExtension from '../common/wrt_xwalk_extension';
-import { DeviceAPIRouter } from './device_api_router';
+import * as DeviceAPIRouter from './device_api_router';
 import { isMainThread, parentPort, workerData } from 'worker_threads';
 import { wrt } from '../browser/wrt';
 
-Object.defineProperty(global, 'serviceType', {
-  value: wrt.getServiceModel(),
-  writable: false
-});
-
 function isServiceApplication() {
   return global['serviceType'] !== 'UI';
 }
@@ -67,7 +62,8 @@ let checkLauncherAlive = (id: string) => {
   }
 }
 
-export function start(id: string, filename: string) {
+function start(id: string, filename: string) {
+  wrt.tv?.serviceMount(id);
   let ids = id.split(':');
   let serviceId = ids[0];
   let packageId = wrt.getPackageId(id);
@@ -88,7 +84,7 @@ export function start(id: string, filename: string) {
   });
 
   console.debug(`serviceType : ${global['serviceType']}`)
-  new DeviceAPIRouter(id, isGlobalService());
+  DeviceAPIRouter.initialize(id, isGlobalService());
   printAppControlData(id);
 
   // This is for awaking up uv loop.
@@ -122,7 +118,7 @@ export function start(id: string, filename: string) {
   }
 }
 
-export function stop(id: string) {
+function stop(id: string) {
   if (dummyTimer)
     clearInterval(dummyTimer);
   try {
@@ -139,19 +135,35 @@ export function stop(id: string) {
   }
 }
 
+function destroy(id: string) {
+  XWalkExtension.cleanup();
+  DeviceAPIRouter.cleanup();
+  wrt.tv?.serviceUmount(id);
+
+  wrt.edge?.destroy(); delete wrt.edge;
+  wrt.mde?.destroy(); delete wrt.mde;
+  wrt.security?.destroy(); delete wrt.security;
+  wrt.tv?.destroy(); delete wrt.tv;
+  wrt.destroy();
+}
+
 function run() {
   let id = workerData.id;
   if (!id) {
     console.debug('workerData.id is empty!');
     process.exit();
   }
-
-  Object.defineProperty(global, 'internalId', {
-    value: id,
-    writable: false
+  Object.defineProperties(global, {
+    'serviceType': {
+      value: wrt.getServiceModel(),
+      writable: false
+    },
+    'internalId': {
+      value: id,
+      writable: false
+    }
   });
 
-  wrt.tv?.serviceMount(id);
   let filename = workerData.filename;
   start(id, filename);
 
@@ -162,10 +174,9 @@ function run() {
     } else if (message.type === 'stop') {
       stop(id);
       setTimeout(() => {
-        XWalkExtension.cleanup();
+        destroy(id);
         parentPort?.postMessage("will-terminate");
         parentPort?.close();
-        wrt.tv?.serviceUmount(id);
       }, message.delay);
     }
   });