From 27e29c1845a4adc73b78ac2db968cb83965c07c6 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 23 Feb 2024 07:36:44 +0100 Subject: [PATCH 1/2] - debugger noise - dump JS threads when GC deadlock - cleanup jiterpreter_dump_stats --- src/mono/browser/runtime/debug.ts | 7 ------- src/mono/browser/runtime/exports-binding.ts | 3 +++ src/mono/browser/runtime/exports.ts | 14 +++++++------- src/mono/browser/runtime/jiterpreter.ts | 14 ++++---------- src/mono/browser/runtime/pthreads/index.ts | 2 +- src/mono/browser/runtime/pthreads/ui-thread.ts | 4 ++-- src/mono/browser/runtime/types/internal.ts | 2 +- src/mono/mono/utils/mono-threads-wasm.c | 8 +++++++- src/mono/mono/utils/mono-threads-wasm.h | 3 +++ src/mono/mono/utils/mono-threads.c | 6 ++++++ 10 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/mono/browser/runtime/debug.ts b/src/mono/browser/runtime/debug.ts index 74c0128f2e4e3..1cbe85aff718a 100644 --- a/src/mono/browser/runtime/debug.ts +++ b/src/mono/browser/runtime/debug.ts @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import BuildConfiguration from "consts:configuration"; - import { INTERNAL, Module, loaderHelpers, runtimeHelpers } from "./globals"; import { toBase64StringImpl } from "./base64"; import cwraps from "./cwraps"; @@ -364,11 +362,6 @@ export function mono_wasm_debugger_log(level: number, message_ptr: CharPtr): voi INTERNAL.logging.debugger(level, message); return; } - - if (BuildConfiguration === "Debug") { - // eslint-disable-next-line no-console - console.debug(`Debugger.Debug: ${message}`); - } } type CallDetails = { diff --git a/src/mono/browser/runtime/exports-binding.ts b/src/mono/browser/runtime/exports-binding.ts index 3e65378483df3..986e6f89a9c50 100644 --- a/src/mono/browser/runtime/exports-binding.ts +++ b/src/mono/browser/runtime/exports-binding.ts @@ -31,6 +31,7 @@ import { mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_unregistered, mono_wasm_pthread_on_pthread_registered, mono_wasm_pthread_set_name, mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop } from "./pthreads"; +import { mono_wasm_dump_threads } from "./pthreads/ui-thread"; // the JS methods would be visible to EMCC linker and become imports of the WASM module @@ -45,6 +46,8 @@ export const mono_wasm_threads_imports = !WasmEnableThreads ? [] : [ // threads.c mono_wasm_eventloop_has_unsettled_interop_promises, + // mono-threads.c + mono_wasm_dump_threads, // diagnostics_server.c mono_wasm_diagnostic_server_on_server_thread_created, mono_wasm_diagnostic_server_on_runtime_server_init, diff --git a/src/mono/browser/runtime/exports.ts b/src/mono/browser/runtime/exports.ts index 8b2984f393b1f..2a4dc08320a0b 100644 --- a/src/mono/browser/runtime/exports.ts +++ b/src/mono/browser/runtime/exports.ts @@ -10,7 +10,7 @@ import WasmEnableExceptionHandling from "consts:wasmEnableExceptionHandling"; import type { RuntimeAPI } from "./types"; import { Module, exportedRuntimeAPI, loaderHelpers, passEmscriptenInternals, runtimeHelpers, setRuntimeGlobals, } from "./globals"; -import { GlobalObjects } from "./types/internal"; +import { GlobalObjects, RuntimeHelpers } from "./types/internal"; import { configureEmscriptenStartup, configureRuntimeStartup, configureWorkerStartup } from "./startup"; import { create_weak_ref } from "./weak-ref"; @@ -22,7 +22,7 @@ import { mono_wasm_stringify_as_error_with_stack } from "./logging"; import { instantiate_asset, instantiate_symbols_asset, instantiate_segmentation_rules_asset } from "./assets"; import { jiterpreter_dump_stats } from "./jiterpreter"; import { forceDisposeProxies } from "./gc-handles"; -import { dumpThreads } from "./pthreads"; +import { mono_wasm_dump_threads } from "./pthreads"; export let runtimeList: RuntimeList; @@ -32,19 +32,19 @@ function initializeExports(globalObjects: GlobalObjects): RuntimeAPI { const globalThisAny = globalThis as any; Object.assign(globals.internal, export_internal()); - Object.assign(runtimeHelpers, { + const rh: Partial = { stringify_as_error_with_stack: mono_wasm_stringify_as_error_with_stack, instantiate_symbols_asset, instantiate_asset, jiterpreter_dump_stats, forceDisposeProxies, instantiate_segmentation_rules_asset, - }); + + }; if (WasmEnableThreads) { - Object.assign(runtimeHelpers, { - dumpThreads, - }); + rh.dumpThreads = mono_wasm_dump_threads; } + Object.assign(runtimeHelpers, rh); const API = export_api(); Object.assign(exportedRuntimeAPI, { diff --git a/src/mono/browser/runtime/jiterpreter.ts b/src/mono/browser/runtime/jiterpreter.ts index 9d47c2e39b1ea..5ef86e182905e 100644 --- a/src/mono/browser/runtime/jiterpreter.ts +++ b/src/mono/browser/runtime/jiterpreter.ts @@ -891,7 +891,7 @@ function generate_wasm( // suites or benchmarks if you've enabled stats const tracesCompiled = getCounter(JiterpCounter.TracesCompiled); if (builder.options.enableStats && tracesCompiled && (tracesCompiled % autoDumpInterval) === 0) - jiterpreter_dump_stats(false, true); + jiterpreter_dump_stats(true); return idx; } catch (exc: any) { @@ -1074,14 +1074,14 @@ export function mono_jiterp_free_method_data_js( mono_jiterp_free_method_data_jit_call(method); } -export function jiterpreter_dump_stats(b?: boolean, concise?: boolean) { +export function jiterpreter_dump_stats(concise?: boolean): void { if (!runtimeHelpers.runtimeReady) { return; } - if (!mostRecentOptions || (b !== undefined)) + if (!mostRecentOptions) mostRecentOptions = getOptions(); - if (!mostRecentOptions.enableStats && (b !== undefined)) + if (!mostRecentOptions.enableStats) return; const backBranchesEmitted = getCounter(JiterpCounter.BackBranchesEmitted), @@ -1243,10 +1243,4 @@ export function jiterpreter_dump_stats(b?: boolean, concise?: boolean) { for (const k in simdFallbackCounters) mono_log_info(`// simd ${k}: ${simdFallbackCounters[k]} fallback insn(s)`); - - if ((typeof (globalThis.setTimeout) === "function") && (b !== undefined)) - setTimeout( - () => jiterpreter_dump_stats(b), - 15000 - ); } diff --git a/src/mono/browser/runtime/pthreads/index.ts b/src/mono/browser/runtime/pthreads/index.ts index a97f0f0f06082..c3128d2be2842 100644 --- a/src/mono/browser/runtime/pthreads/index.ts +++ b/src/mono/browser/runtime/pthreads/index.ts @@ -6,7 +6,7 @@ export { mono_wasm_pthread_ptr, update_thread_info, isMonoThreadMessage, monoThreadInfo, } from "./shared"; export { - dumpThreads, thread_available, cancelThreads, is_thread_available, + mono_wasm_dump_threads, thread_available, cancelThreads, is_thread_available, populateEmscriptenPool, mono_wasm_init_threads, init_finalizer_thread, waitForThread, replaceEmscriptenPThreadUI } from "./ui-thread"; diff --git a/src/mono/browser/runtime/pthreads/ui-thread.ts b/src/mono/browser/runtime/pthreads/ui-thread.ts index c7fb54a66e48c..baa72e7a3b975 100644 --- a/src/mono/browser/runtime/pthreads/ui-thread.ts +++ b/src/mono/browser/runtime/pthreads/ui-thread.ts @@ -182,7 +182,7 @@ export function cancelThreads() { } } -export function dumpThreads(): void { +export function mono_wasm_dump_threads(): void { if (!WasmEnableThreads) return; mono_log_info("Dumping web worker info as seen by UI thread, it could be stale: "); const emptyInfo: PThreadInfo = { @@ -278,7 +278,7 @@ export function replaceEmscriptenPThreadUI(modulePThread: PThreadLibrary): void } }; if (BuildConfiguration === "Debug") { - (globalThis as any).dumpThreads = dumpThreads; + (globalThis as any).dumpThreads = mono_wasm_dump_threads; (globalThis as any).getModulePThread = getModulePThread; } } diff --git a/src/mono/browser/runtime/types/internal.ts b/src/mono/browser/runtime/types/internal.ts index 4c9fa7babc62f..7d4eb89d0f3c9 100644 --- a/src/mono/browser/runtime/types/internal.ts +++ b/src/mono/browser/runtime/types/internal.ts @@ -235,7 +235,7 @@ export type RuntimeHelpers = { instantiate_asset: (asset: AssetEntry, url: string, bytes: Uint8Array) => void, instantiate_symbols_asset: (pendingAsset: AssetEntryInternal) => Promise, instantiate_segmentation_rules_asset: (pendingAsset: AssetEntryInternal) => Promise, - jiterpreter_dump_stats?: (x: boolean) => string, + jiterpreter_dump_stats?: (concise?: boolean) => void, forceDisposeProxies: (disposeMethods: boolean, verbose: boolean) => void, dumpThreads: () => void, } diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index 1746c7213e96d..ca11139ce43b3 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -541,9 +541,15 @@ mono_threads_wasm_on_thread_registered (void) } #ifndef DISABLE_THREADS +static pthread_t deputy_thread_tid; extern void mono_wasm_start_deputy_thread_async (void); extern void mono_wasm_trace_logger (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data); -static pthread_t deputy_thread_tid; +extern void mono_wasm_dump_threads (void); + +void mono_wasm_dump_threads_async (void) +{ + mono_threads_wasm_async_run_in_target_thread (mono_threads_wasm_ui_thread_tid (), mono_wasm_dump_threads); +} gboolean mono_threads_wasm_is_deputy_thread (void) diff --git a/src/mono/mono/utils/mono-threads-wasm.h b/src/mono/mono/utils/mono-threads-wasm.h index 13668709357db..1aa68ee7d329c 100644 --- a/src/mono/mono/utils/mono-threads-wasm.h +++ b/src/mono/mono/utils/mono-threads-wasm.h @@ -28,6 +28,9 @@ mono_threads_wasm_ui_thread_tid (void); #ifndef DISABLE_THREADS +void +mono_wasm_dump_threads_async (void); + gboolean mono_threads_wasm_is_deputy_thread (void); diff --git a/src/mono/mono/utils/mono-threads.c b/src/mono/mono/utils/mono-threads.c index 515cde6eebad5..14a00bc915429 100644 --- a/src/mono/mono/utils/mono-threads.c +++ b/src/mono/mono/utils/mono-threads.c @@ -281,6 +281,12 @@ mono_threads_end_global_suspend (void) static void dump_threads (void) { +#ifdef HOST_BROWSER +#ifndef DISABLE_THREADS + mono_wasm_dump_threads_async (); +#endif +#endif + MonoThreadInfo *cur = mono_thread_info_current (); g_async_safe_printf ("STATE CUE CARD: (? means a positive number, usually 1 or 2, * means any number)\n"); From 036fa9ed9c03ddfa676ccfdd19690bf62bf2fba3 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 23 Feb 2024 08:01:12 +0100 Subject: [PATCH 2/2] fix --- src/mono/browser/runtime/exports-internal.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/browser/runtime/exports-internal.ts b/src/mono/browser/runtime/exports-internal.ts index 80c52669fb3ad..61c6e1fe6e3f4 100644 --- a/src/mono/browser/runtime/exports-internal.ts +++ b/src/mono/browser/runtime/exports-internal.ts @@ -23,14 +23,14 @@ import { mono_wasm_get_func_id_to_name_mappings } from "./logging"; import { monoStringToStringUnsafe } from "./strings"; import { mono_wasm_bind_cs_function } from "./invoke-cs"; -import { dumpThreads, thread_available } from "./pthreads"; +import { mono_wasm_dump_threads, thread_available } from "./pthreads"; export function export_internal(): any { return { // tests mono_wasm_exit: (exit_code: number) => { Module.err("early exit " + exit_code); }, forceDisposeProxies, - dumpThreads: WasmEnableThreads ? dumpThreads : undefined, + mono_wasm_dump_threads: WasmEnableThreads ? mono_wasm_dump_threads : undefined, // with mono_wasm_debugger_log and mono_wasm_trace_logger logging: undefined,