Skip to content

Commit

Permalink
[browser][MT] dump JS threads when GC deadlock (dotnet#98843)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelsavara committed Feb 26, 2024
1 parent c55c4d5 commit 8ccb71e
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 31 deletions.
7 changes: 0 additions & 7 deletions src/mono/browser/runtime/debug.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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 = {
Expand Down
3 changes: 3 additions & 0 deletions src/mono/browser/runtime/exports-binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/mono/browser/runtime/exports-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
14 changes: 7 additions & 7 deletions src/mono/browser/runtime/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;

Expand All @@ -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<RuntimeHelpers> = {
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, {
Expand Down
14 changes: 4 additions & 10 deletions src/mono/browser/runtime/jiterpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
);
}
2 changes: 1 addition & 1 deletion src/mono/browser/runtime/pthreads/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
4 changes: 2 additions & 2 deletions src/mono/browser/runtime/pthreads/ui-thread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/mono/browser/runtime/types/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export type RuntimeHelpers = {
instantiate_asset: (asset: AssetEntry, url: string, bytes: Uint8Array) => void,
instantiate_symbols_asset: (pendingAsset: AssetEntryInternal) => Promise<void>,
instantiate_segmentation_rules_asset: (pendingAsset: AssetEntryInternal) => Promise<void>,
jiterpreter_dump_stats?: (x: boolean) => string,
jiterpreter_dump_stats?: (concise?: boolean) => void,
forceDisposeProxies: (disposeMethods: boolean, verbose: boolean) => void,
dumpThreads: () => void,
}
Expand Down
8 changes: 7 additions & 1 deletion src/mono/mono/utils/mono-threads-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/utils/mono-threads-wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
6 changes: 6 additions & 0 deletions src/mono/mono/utils/mono-threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down

0 comments on commit 8ccb71e

Please sign in to comment.