From dc19d94f302de3e48620be09b4a09e876cfeabc7 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Fri, 15 Oct 2021 11:43:26 +0900 Subject: [PATCH] [Service] Call destroy() of FunctionTemplate 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 --- wrt_app/common/wrt_xwalk_extension.ts | 19 ++++++++---- wrt_app/service/device_api_router.ts | 10 +++++++ wrt_app/service/service_runner.ts | 43 +++++++++++++++++---------- 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/wrt_app/common/wrt_xwalk_extension.ts b/wrt_app/common/wrt_xwalk_extension.ts index 4e32394f..9ea29f45 100644 --- a/wrt_app/common/wrt_xwalk_extension.ts +++ b/wrt_app/common/wrt_xwalk_extension.ts @@ -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; } diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 98cbe038..955fc7d1 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -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 diff --git a/wrt_app/service/service_runner.ts b/wrt_app/service/service_runner.ts index d110017a..d3a47f3e 100644 --- a/wrt_app/service/service_runner.ts +++ b/wrt_app/service/service_runner.ts @@ -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); } }); -- 2.34.1