From 40979dc04ef401631d265cb012bfd8b7c87c9cac Mon Sep 17 00:00:00 2001 From: Samuel Sadok Date: Wed, 6 Jul 2022 19:23:09 +0200 Subject: [PATCH] improve instrumentation for memory leak detection --- cpp/README.md | 9 +++++++++ cpp/libfibre.cpp | 24 ++++++++++++++++++++++++ js/example.html | 10 ++++++++++ js/fibre.js | 46 ++++++++++++++++++++++++++-------------------- 4 files changed, 69 insertions(+), 20 deletions(-) diff --git a/cpp/README.md b/cpp/README.md index d583ab2..ce09d32 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -98,3 +98,12 @@ To compile your application you need to link against the libfibre binary (`-L/pa - Fibre currently targets C++11 to maximize compatibility with other projects - Notes on platform independent programming: - Don't use the keyword `interface` (defined as a macro on Windows in `rpc.h`) + +# Debugging Memory Leaks in WASM + +This works only in JS, not in dart: + +- Add `-fsanitize=leak` to CFLAGS +- Add `-sINITIAL_MEMORY=104857600` to LDFLAGS +- Compile +- In example.html press "Leak Check" diff --git a/cpp/libfibre.cpp b/cpp/libfibre.cpp index 65fb315..68352d4 100644 --- a/cpp/libfibre.cpp +++ b/cpp/libfibre.cpp @@ -637,3 +637,27 @@ void libfibre_run_tasks(LibFibreCtx* ctx, LibFibreTask* tasks, size_t n_tasks, L *out_tasks = ctx->shadow_task_queue.data(); *n_out_tasks = ctx->shadow_task_queue.size(); } + + +extern "C" { +#if defined(__has_feature) +# if __has_feature(address_sanitizer) +# define LEAK_CHECK 1 +# else +# define LEAK_CHECK 0 +# endif +#else +# define LEAK_CHECK 0 +#endif + +#if LEAK_CHECK +#include +FIBRE_PUBLIC void do_leak_check() { + __lsan_do_recoverable_leak_check(); +} +#else +FIBRE_PUBLIC int do_leak_check() { + return 0; +} +#endif +} diff --git a/js/example.html b/js/example.html index f438813..2382f8e 100644 --- a/js/example.html +++ b/js/example.html @@ -7,6 +7,7 @@

not connected

+ diff --git a/js/fibre.js b/js/fibre.js index a7b1c8d..b7bc2f1 100644 --- a/js/fibre.js +++ b/js/fibre.js @@ -910,28 +910,34 @@ class Domain { } } -export function fibreOpen(log_verbosity = 5) { +export function fibreOpen(log_verbosity = 3) { return new Promise(async (resolve) => { let Module = { - instantiateWasm: async (info, receiveInstance) => { - const isWebpack = typeof __webpack_require__ === 'function'; - const wasmPath = isWebpack ? (await import("!!file-loader!./libfibre-wasm.wasm")).default - : "./libfibre-wasm.wasm"; - - let result; - if (typeof navigator === 'object') { - // Running in browser - const response = fetch(wasmPath, { credentials: 'same-origin' }); - result = await WebAssembly.instantiateStreaming(response, info); - } else { - // Running in bare NodeJS - const fsPromises = (await import('fs/promises')).default; - const response = await fsPromises.readFile('/Data/Projects/fibre/js/libfibre-wasm.wasm'); - result = await WebAssembly.instantiate(response, info); - } - receiveInstance(result['instance']); - return {}; - } +// instantiateWasm: async (info, receiveInstance) => { +// const isWebpack = typeof __webpack_require__ === 'function'; +// const wasmPath = isWebpack ? (await import("!!file-loader!./libfibre-wasm.wasm")).default +// : "./libfibre-wasm.wasm"; +// +// let instantiationResult; +// var arrayBufferResult; +// if (typeof navigator === 'object') { +// // Running in browser +// const response = fetch(wasmPath, { credentials: 'same-origin' }); +// arrayBufferResult = (await response).clone().arrayBuffer(); +// instantiationResult = await WebAssembly.instantiateStreaming(response, info); +// console.log(instantiationResult); +// //arrayBufferResult = (await response).clone().arrayBuffer(); +// } else { +// // Running in bare NodeJS +// const fsPromises = (await import('fs/promises')).default; +// const response = await fsPromises.readFile('/Data/Projects/fibre/js/libfibre-wasm.wasm'); +// instantiationResult = await WebAssembly.instantiate(response, info); +// } +// +// //wasmOffsetConverter = new WasmOffsetConverter(new Uint8Array(arrayBufferResult), instantiationResult.module); +// receiveInstance(instantiationResult['instance'], null, arrayBufferResult); +// return {}; +// } }; Module = await wasm(Module); await Module.ready;