Skip to content

Commit

Permalink
[browser][MT] withDumpThreadsOnNonZeroExit (#98052)
Browse files Browse the repository at this point in the history
Co-authored-by: Marek Fišera <mara@neptuo.com>
  • Loading branch information
pavelsavara and maraf authored Feb 7, 2024
1 parent 24d149c commit 97aba78
Show file tree
Hide file tree
Showing 27 changed files with 207 additions and 117 deletions.
6 changes: 3 additions & 3 deletions src/mono/browser/runtime/cwraps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
MonoType, MonoObjectRef, MonoStringRef, JSMarshalerArguments
} from "./types/internal";
import type { VoidPtr, CharPtrPtr, Int32Ptr, CharPtr, ManagedPointer } from "./types/emscripten";
import { linkerEnableAotProfiler, linkerEnableBrowserProfiler, Module } from "./globals";
import { Module, runtimeHelpers } from "./globals";
import { mono_log_error } from "./logging";
import { mono_assert } from "./globals";

Expand Down Expand Up @@ -60,8 +60,8 @@ const fn_signatures: SigLine[] = [
[true, "mono_wasm_getenv", "number", ["string"]],
[true, "mono_wasm_set_main_args", "void", ["number", "number"]],
// These two need to be lazy because they may be missing
[() => !linkerEnableAotProfiler, "mono_wasm_profiler_init_aot", "void", ["string"]],
[() => !linkerEnableBrowserProfiler, "mono_wasm_profiler_init_aot", "void", ["string"]],
[() => !runtimeHelpers.emscriptenBuildOptions.enableAotProfiler, "mono_wasm_profiler_init_aot", "void", ["string"]],
[() => !runtimeHelpers.emscriptenBuildOptions.enableBrowserProfiler, "mono_wasm_profiler_init_aot", "void", ["string"]],
[true, "mono_wasm_profiler_init_browser", "void", ["number"]],
[false, "mono_wasm_exec_regression", "number", ["number", "string"]],
[false, "mono_wasm_invoke_method_bound", "number", ["number", "number", "number"]],
Expand Down
3 changes: 3 additions & 0 deletions src/mono/browser/runtime/dotnet.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,9 @@ type RuntimeAPI = {
productVersion: string;
gitHash: string;
buildConfiguration: string;
wasmEnableThreads: boolean;
wasmEnableSIMD: boolean;
wasmEnableExceptionHandling: boolean;
};
} & APIType;
type ModuleAPI = {
Expand Down
18 changes: 4 additions & 14 deletions src/mono/browser/runtime/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,19 +189,6 @@ mono_wasm_load_runtime (const char *unused, int debug_level)
mono_wasm_link_icu_shim ();
#endif

#ifndef DISABLE_THREADS
monoeg_g_setenv ("MONO_SLEEP_ABORT_LIMIT", "5000", 0);
#endif

// monoeg_g_setenv ("DOTNET_DebugWriteToStdErr", "1", 0);

#ifdef DEBUG
// monoeg_g_setenv ("MONO_LOG_LEVEL", "debug", 0);
// monoeg_g_setenv ("MONO_LOG_MASK", "gc", 0);
// Setting this env var allows Diagnostic.Debug to write to stderr. In a browser environment this
// output will be sent to the console. Right now this is the only way to emit debug logging from
// corlib assemblies.
#endif
// When the list of app context properties changes, please update RuntimeConfigReservedProperties for
// target _WasmGenerateRuntimeConfig in BrowserWasmApp.targets file
const char *appctx_keys[2];
Expand Down Expand Up @@ -372,7 +359,10 @@ mono_wasm_exec_regression (int verbose_level, char *image)
EMSCRIPTEN_KEEPALIVE int
mono_wasm_exit (int exit_code)
{
mono_jit_cleanup (root_domain);
if (exit_code == 0)
{
mono_jit_cleanup (root_domain);
}
fflush (stdout);
fflush (stderr);
emscripten_force_exit (exit_code);
Expand Down
18 changes: 9 additions & 9 deletions src/mono/browser/runtime/es6/dotnet.es6.lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const RUN_AOT_COMPILATION = process.env.RUN_AOT_COMPILATION === "1";
var methodIndexByName = undefined;
var gitHash = undefined;

function setup(linkerSetup) {
function setup(emscriptenBuildOptions) {
// USE_PTHREADS is emscripten's define symbol, which is passed to acorn optimizer, so we could use it here
#if USE_PTHREADS
const modulePThread = PThread;
Expand Down Expand Up @@ -43,8 +43,7 @@ function setup(linkerSetup) {
updateMemoryViews,
getMemory: () => { return wasmMemory; },
getWasmIndirectFunctionTable: () => { return wasmTable; },
...linkerSetup
});
}, emscriptenBuildOptions);

#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) {
Expand Down Expand Up @@ -83,11 +82,12 @@ function injectDependencies() {
#endif

DotnetSupportLib["$DOTNET__postset"] = `DOTNET.setup({ ` +
`linkerWasmEnableSIMD: ${WASM_ENABLE_SIMD ? "true" : "false"},` +
`linkerWasmEnableEH: ${WASM_ENABLE_EH ? "true" : "false"},` +
`linkerEnableAotProfiler: ${ENABLE_AOT_PROFILER ? "true" : "false"}, ` +
`linkerEnableBrowserProfiler: ${ENABLE_BROWSER_PROFILER ? "true" : "false"}, ` +
`linkerRunAOTCompilation: ${RUN_AOT_COMPILATION ? "true" : "false"}, ` +
`wasmEnableSIMD: ${WASM_ENABLE_SIMD ? "true" : "false"},` +
`wasmEnableEH: ${WASM_ENABLE_EH ? "true" : "false"},` +
`enableAotProfiler: ${ENABLE_AOT_PROFILER ? "true" : "false"}, ` +
`enableBrowserProfiler: ${ENABLE_BROWSER_PROFILER ? "true" : "false"}, ` +
`runAOTCompilation: ${RUN_AOT_COMPILATION ? "true" : "false"}, ` +
`wasmEnableThreads: ${USE_PTHREADS ? "true" : "false"}, ` +
`gitHash: "${gitHash}", ` +
`});`;

Expand All @@ -96,4 +96,4 @@ function injectDependencies() {
}


// var methodIndexByName wil be appended below by the MSBuild in browser.proj
// var methodIndexByName wil be appended below by the MSBuild in browser.proj via exports-linker.ts
4 changes: 3 additions & 1 deletion src/mono/browser/runtime/exports-binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { mono_interp_jit_wasm_entry_trampoline, mono_interp_record_interp_entry
import { mono_interp_jit_wasm_jit_call_trampoline, mono_interp_invoke_wasm_jit_call_trampoline, mono_interp_flush_jitcall_queue } from "./jiterpreter-jit-call";
import { mono_wasm_resolve_or_reject_promise } from "./marshal-to-js";
import { mono_wasm_eventloop_has_unsettled_interop_promises } from "./pthreads/shared/eventloop";
import { mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_unregistered, mono_wasm_pthread_on_pthread_registered } from "./pthreads/worker";
import { mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_unregistered, mono_wasm_pthread_on_pthread_registered, mono_wasm_pthread_set_name } from "./pthreads/worker";
import { mono_wasm_schedule_timer, schedule_background_exec } from "./scheduling";
import { mono_wasm_asm_loaded } from "./startup";
import { mono_wasm_diagnostic_server_on_server_thread_created } from "./diagnostics/server_pthread";
Expand All @@ -37,6 +37,8 @@ export const mono_wasm_threads_imports = !WasmEnableThreads ? [] : [
mono_wasm_pthread_on_pthread_registered,
mono_wasm_pthread_on_pthread_attached,
mono_wasm_pthread_on_pthread_unregistered,
mono_wasm_pthread_set_name,

// threads.c
mono_wasm_eventloop_has_unsettled_interop_promises,
// diagnostics_server.c
Expand Down
15 changes: 14 additions & 1 deletion src/mono/browser/runtime/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

import ProductVersion from "consts:productVersion";
import BuildConfiguration from "consts:configuration";
import WasmEnableThreads from "consts:wasmEnableThreads";
import WasmEnableSIMD from "consts:wasmEnableSIMD";
import WasmEnableExceptionHandling from "consts:wasmEnableExceptionHandling";

import type { RuntimeAPI } from "./types";

import { Module, exportedRuntimeAPI, loaderHelpers, passEmscriptenInternals, runtimeHelpers, setRuntimeGlobals, } from "./globals";
Expand All @@ -18,6 +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/browser";

export let runtimeList: RuntimeList;

Expand All @@ -35,6 +40,11 @@ function initializeExports(globalObjects: GlobalObjects): RuntimeAPI {
forceDisposeProxies,
instantiate_segmentation_rules_asset,
});
if (WasmEnableThreads) {
Object.assign(runtimeHelpers, {
dumpThreads,
});
}

const API = export_api();
Object.assign(exportedRuntimeAPI, {
Expand All @@ -43,7 +53,10 @@ function initializeExports(globalObjects: GlobalObjects): RuntimeAPI {
runtimeBuildInfo: {
productVersion: ProductVersion,
gitHash: runtimeHelpers.gitHash,
buildConfiguration: BuildConfiguration
buildConfiguration: BuildConfiguration,
wasmEnableThreads: WasmEnableThreads,
wasmEnableSIMD: WasmEnableSIMD,
wasmEnableExceptionHandling: WasmEnableExceptionHandling,
},
...API,
});
Expand Down
17 changes: 4 additions & 13 deletions src/mono/browser/runtime/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import gitHash from "consts:gitHash";

import { RuntimeAPI } from "./types/index";
import type { GlobalObjects, EmscriptenInternals, RuntimeHelpers, LoaderHelpers, DotnetModuleInternal, PromiseAndController } from "./types/internal";
import type { GlobalObjects, EmscriptenInternals, RuntimeHelpers, LoaderHelpers, DotnetModuleInternal, PromiseAndController, EmscriptenBuildOptions } from "./types/internal";
import { mono_log_error } from "./logging";

// these are our public API (except internal)
Expand All @@ -30,23 +30,14 @@ export let exportedRuntimeAPI: RuntimeAPI = null as any;
export let runtimeHelpers: RuntimeHelpers = null as any;
export let loaderHelpers: LoaderHelpers = null as any;

export let linkerWasmEnableSIMD = true;
export let linkerWasmEnableEH = true;
export let linkerEnableAotProfiler = false;
export let linkerEnableBrowserProfiler = false;
export let linkerRunAOTCompilation = false;
export let _runtimeModuleLoaded = false; // please keep it in place also as rollup guard

export function passEmscriptenInternals(internals: EmscriptenInternals): void {
export function passEmscriptenInternals(internals: EmscriptenInternals, emscriptenBuildOptions: EmscriptenBuildOptions): void {
runtimeHelpers.emscriptenBuildOptions = emscriptenBuildOptions;

ENVIRONMENT_IS_PTHREAD = internals.isPThread;
linkerWasmEnableSIMD = internals.linkerWasmEnableSIMD;
linkerWasmEnableEH = internals.linkerWasmEnableEH;
linkerEnableAotProfiler = internals.linkerEnableAotProfiler;
linkerEnableBrowserProfiler = internals.linkerEnableBrowserProfiler;
linkerRunAOTCompilation = internals.linkerRunAOTCompilation;
runtimeHelpers.quit = internals.quit_;
runtimeHelpers.ExitStatus = internals.ExitStatus;
runtimeHelpers.moduleGitHash = internals.gitHash;
runtimeHelpers.getMemory = internals.getMemory;
runtimeHelpers.getWasmIndirectFunctionTable = internals.getWasmIndirectFunctionTable;
runtimeHelpers.updateMemoryViews = internals.updateMemoryViews;
Expand Down
6 changes: 3 additions & 3 deletions src/mono/browser/runtime/jiterpreter-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import WasmEnableThreads from "consts:wasmEnableThreads";
import { NativePointer, ManagedPointer, VoidPtr } from "./types/emscripten";
import { Module, mono_assert, runtimeHelpers, linkerRunAOTCompilation } from "./globals";
import { Module, mono_assert, runtimeHelpers } from "./globals";
import { WasmOpcode, WasmSimdOpcode, WasmValtype } from "./jiterpreter-opcodes";
import { MintOpcode } from "./mintops";
import cwraps from "./cwraps";
Expand Down Expand Up @@ -2017,8 +2017,8 @@ export function jiterpreter_allocate_tables() {
// then create special placeholder functions that examine the rmethod to determine which kind
// of method is being called.
const traceTableSize = options.tableSize,
jitCallTableSize = linkerRunAOTCompilation ? options.tableSize : 1,
interpEntryTableSize = linkerRunAOTCompilation ? options.aotTableSize : 1,
jitCallTableSize = runtimeHelpers.emscriptenBuildOptions.runAOTCompilation ? options.tableSize : 1,
interpEntryTableSize = runtimeHelpers.emscriptenBuildOptions.runAOTCompilation ? options.aotTableSize : 1,
numInterpEntryTables = JiterpreterTable.LAST - JiterpreterTable.InterpEntryStatic0 + 1,
totalSize = traceTableSize + jitCallTableSize + (numInterpEntryTables * interpEntryTableSize) + 1,
wasmTable = getWasmFunctionTable();
Expand Down
8 changes: 7 additions & 1 deletion src/mono/browser/runtime/loader/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,22 @@ export function normalizeConfig() {
config.pthreadPoolSize = 7;
}

// this is how long the Mono GC will try to wait for all threads to be suspended before it gives up and aborts the process
if (WasmEnableThreads && config.environmentVariables["MONO_SLEEP_ABORT_LIMIT"] === undefined) {
config.environmentVariables["MONO_SLEEP_ABORT_LIMIT"] = "5000";
}

// Default values (when WasmDebugLevel is not set)
// - Build (debug) => debugBuild=true & debugLevel=-1 => -1
// - Build (release) => debugBuild=true & debugLevel=0 => 0
// - Publish (debug) => debugBuild=false & debugLevel=-1 => 0
// - Publish (release) => debugBuild=false & debugLevel=0 => 0
config.debugLevel = hasDebuggingEnabled(config) ? config.debugLevel : 0;

if (config.diagnosticTracing === undefined && BuildConfiguration === "Debug") {
if (BuildConfiguration === "Debug" && config.diagnosticTracing === undefined) {
config.diagnosticTracing = true;
}

if (config.applicationCulture) {
// If a culture is specified via start options use that to initialize the Emscripten \ .NET culture.
config.environmentVariables!["LANG"] = `${config.applicationCulture}.UTF-8`;
Expand Down
3 changes: 3 additions & 0 deletions src/mono/browser/runtime/loader/exit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ export function mono_exit(exit_code: number, reason?: any): void {
if (exit_code === 0 && loaderHelpers.config?.interopCleanupOnExit) {
runtimeHelpers.forceDisposeProxies(true, true);
}
if (WasmEnableThreads && exit_code !== 0 && loaderHelpers.config?.dumpThreadsOnNonZeroExit) {
runtimeHelpers.dumpThreads();
}
}
}
catch (err) {
Expand Down
4 changes: 2 additions & 2 deletions src/mono/browser/runtime/loader/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type { MonoConfig, RuntimeAPI } from "../types";
import { assert_runtime_running, installUnhandledErrorHandler, is_exited, is_runtime_running, mono_exit } from "./exit";
import { assertIsControllablePromise, createPromiseController, getPromiseController } from "./promise-controller";
import { mono_download_assets, resolve_single_asset_path, retrieve_asset_download } from "./assets";
import { mono_log_error, mono_set_thread_name, setup_proxy_console } from "./logging";
import { mono_log_error, set_thread_prefix, setup_proxy_console } from "./logging";
import { invokeLibraryInitializers } from "./libraryInitializers";
import { deep_merge_config, hasDebuggingEnabled } from "./config";
import { logDownloadStatsToConsole, purgeUnusedCacheEntriesAsync } from "./assetsCache";
Expand Down Expand Up @@ -114,7 +114,7 @@ export function setLoaderGlobals(
mono_download_assets,
resolve_single_asset_path,
setup_proxy_console,
mono_set_thread_name,
set_thread_prefix,
logDownloadStatsToConsole,
purgeUnusedCacheEntriesAsync,
installUnhandledErrorHandler,
Expand Down
4 changes: 2 additions & 2 deletions src/mono/browser/runtime/loader/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ let theConsoleApi: any;
let originalConsoleMethods: any;
let threadNamePrefix: string;

export function mono_set_thread_name(threadName: string) {
threadNamePrefix = threadName;
export function set_thread_prefix(threadPrefix: string) {
threadNamePrefix = threadPrefix;
}

export function mono_log_debug(msg: string, ...data: any[]) {
Expand Down
13 changes: 13 additions & 0 deletions src/mono/browser/runtime/loader/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,19 @@ export class HostBuilder implements DotnetHostBuilder {
}
}

// internal
withDumpThreadsOnNonZeroExit(): DotnetHostBuilder {
try {
deep_merge_config(monoConfig, {
dumpThreadsOnNonZeroExit: true
});
return this;
} catch (err) {
mono_exit(1, err);
throw err;
}
}

// internal
withAssertAfterExit(): DotnetHostBuilder {
try {
Expand Down
4 changes: 2 additions & 2 deletions src/mono/browser/runtime/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { CharPtr, VoidPtr } from "./types/emscripten";

let prefix = "MONO_WASM: ";

export function mono_set_thread_name(threadName: string) {
prefix = `[${threadName}] MONO_WASM: `;
export function set_thread_prefix(threadPrefix: string) {
prefix = `[${threadPrefix}] MONO_WASM: `;
}

export function mono_log_debug(msg: string, ...data: any) {
Expand Down
6 changes: 3 additions & 3 deletions src/mono/browser/runtime/profiler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { ENVIRONMENT_IS_WEB, linkerEnableAotProfiler, linkerEnableBrowserProfiler, mono_assert, runtimeHelpers } from "./globals";
import { ENVIRONMENT_IS_WEB, mono_assert, runtimeHelpers } from "./globals";
import { MonoMethod, AOTProfilerOptions, BrowserProfilerOptions } from "./types/internal";
import { profiler_c_functions as cwraps } from "./cwraps";
import { utf8ToString } from "./strings";
Expand All @@ -15,7 +15,7 @@ import { utf8ToString } from "./strings";
// DumpAotProfileData stores the data into INTERNAL.aotProfileData.
//
export function mono_wasm_init_aot_profiler(options: AOTProfilerOptions): void {
mono_assert(linkerEnableAotProfiler, "AOT profiler is not enabled, please use <WasmProfilers>aot;</WasmProfilers> in your project file.");
mono_assert(runtimeHelpers.emscriptenBuildOptions.enableAotProfiler, "AOT profiler is not enabled, please use <WasmProfilers>aot;</WasmProfilers> in your project file.");
if (options == null)
options = {};
if (!("writeAt" in options))
Expand All @@ -27,7 +27,7 @@ export function mono_wasm_init_aot_profiler(options: AOTProfilerOptions): void {
}

export function mono_wasm_init_browser_profiler(options: BrowserProfilerOptions): void {
mono_assert(linkerEnableBrowserProfiler, "Browser profiler is not enabled, please use <WasmProfilers>browser;</WasmProfilers> in your project file.");
mono_assert(runtimeHelpers.emscriptenBuildOptions.enableBrowserProfiler, "Browser profiler is not enabled, please use <WasmProfilers>browser;</WasmProfilers> in your project file.");
if (options == null)
options = {};
const arg = "browser:";
Expand Down
Loading

0 comments on commit 97aba78

Please sign in to comment.