Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[browser][MT] withDumpThreadsOnNonZeroExit #98052

Merged
merged 8 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.linkerEnableAotProfiler, "mono_wasm_profiler_init_aot", "void", ["string"]],
[() => !runtimeHelpers.emscriptenBuildOptions.linkerEnableBrowserProfiler, "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
10 changes: 5 additions & 5 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 @@ -88,12 +87,13 @@ function injectDependencies() {
`linkerEnableAotProfiler: ${ENABLE_AOT_PROFILER ? "true" : "false"}, ` +
`linkerEnableBrowserProfiler: ${ENABLE_BROWSER_PROFILER ? "true" : "false"}, ` +
`linkerRunAOTCompilation: ${RUN_AOT_COMPILATION ? "true" : "false"}, ` +
`gitHash: "${gitHash}", ` +
`linkerUseThreads: ${USE_PTHREADS ? "true" : "false"}, ` +
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
`moduleGitHash: "${gitHash}", ` +
`});`;

autoAddDeps(DotnetSupportLib, "$DOTNET");
mergeInto(LibraryManager.library, DotnetSupportLib);
}


// 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
16 changes: 4 additions & 12 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,20 +30,12 @@ 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;
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.linkerRunAOTCompilation ? options.tableSize : 1,
interpEntryTableSize = runtimeHelpers.emscriptenBuildOptions.linkerRunAOTCompilation ? options.aotTableSize : 1,
numInterpEntryTables = JiterpreterTable.LAST - JiterpreterTable.InterpEntryStatic0 + 1,
totalSize = traceTableSize + jitCallTableSize + (numInterpEntryTables * interpEntryTableSize) + 1,
wasmTable = getWasmFunctionTable();
Expand Down
7 changes: 6 additions & 1 deletion src/mono/browser/runtime/loader/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ export function normalizeConfig() {
// ActiveIssue https://github.com/dotnet/runtime/issues/75602
config.pthreadPoolSize = 7;
}
if (WasmEnableThreads && config.environmentVariables["MONO_SLEEP_ABORT_LIMIT"] === undefined) {
config.environmentVariables["MONO_SLEEP_ABORT_LIMIT"] = "5000";
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
}


// Default values (when WasmDebugLevel is not set)
// - Build (debug) => debugBuild=true & debugLevel=-1 => -1
Expand All @@ -200,9 +204,10 @@ export function normalizeConfig() {
// - 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?.dumpThreadsOnExit) {
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
withDumpThreadsOnExit(): DotnetHostBuilder {
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
try {
deep_merge_config(monoConfig, {
dumpThreadsOnExit: true
});
return this;
} catch (err) {
mono_exit(1, err);
throw err;
}
}

// internal
withAssertAfterExit(): DotnetHostBuilder {
try {
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.linkerEnableAotProfiler, "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.linkerEnableBrowserProfiler, "Browser profiler is not enabled, please use <WasmProfilers>browser;</WasmProfilers> in your project file.");
if (options == null)
options = {};
const arg = "browser:";
Expand Down
39 changes: 37 additions & 2 deletions src/mono/browser/runtime/pthreads/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

import WasmEnableThreads from "consts:wasmEnableThreads";

import { MonoWorkerToMainMessage, pthreadPtr } from "../shared/types";
import { MonoWorkerToMainMessage, PThreadInfo, pthreadPtr } from "../shared/types";
import { MonoThreadMessage } from "../shared";
import { PThreadWorker, allocateUnusedWorker, getRunningWorkers, getUnusedWorkerPool, getWorker, loadWasmModuleToWorker } from "../shared/emscripten-internals";
import { createPromiseController, mono_assert, runtimeHelpers } from "../../globals";
import { MainToWorkerMessageType, PromiseAndController, PromiseController, WorkerToMainMessageType, monoMessageSymbol } from "../../types/internal";
import { mono_log_info } from "../../logging";
import { monoThreadInfo } from "../worker";

const threadPromises: Map<pthreadPtr, PromiseController<Thread>[]> = new Map();

Expand Down Expand Up @@ -101,6 +103,7 @@ function monoWorkerMessageHandler(worker: PThreadWorker, ev: MessageEvent<any>):
case WorkerToMainMessageType.monoAttached:
case WorkerToMainMessageType.enabledInterop:
case WorkerToMainMessageType.monoUnRegistered:
case WorkerToMainMessageType.updateInfo:
worker.info = Object.assign(worker.info!, message.info, {});
break;
default:
Expand Down Expand Up @@ -168,4 +171,36 @@ export function cancelThreads() {
worker.postMessage({ cmd: "cancel" });
}
}
}
}

export function dumpThreads(): void {
if (!WasmEnableThreads) return;
mono_log_info("Dumping web worker info as seen by UI thread, it could be stale: ");
const emptyInfo = {
pthreadId: 0,
threadPrefix: " - ",
threadName: "????",
isRunning: false,
isAttached: false,
isExternalEventLoop: false,
reuseCount: 0,
};
const threadInfos: PThreadInfo[] = [
Object.assign({}, emptyInfo, monoThreadInfo), // UI thread
];
for (const worker of getRunningWorkers()) {
threadInfos.push(Object.assign({}, emptyInfo, worker.info));
}
for (const worker of getUnusedWorkerPool()) {
threadInfos.push(Object.assign({}, emptyInfo, worker.info));
}
threadInfos.forEach((info, i) => {
const idx = (i + "").padStart(2, "0");
const isRunning = (info.isRunning + "").padStart(5, " ");
const isAttached = (info.isAttached + "").padStart(5, " ");
const isEventLoop = (info.isExternalEventLoop + "").padStart(5, " ");
const reuseCount = (info.reuseCount + "").padStart(3, " ");
// eslint-disable-next-line no-console
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
console.info(`${idx} | ${info.threadPrefix}: isRunning:${isRunning} isAttached:${isAttached} isEventLoop:${isEventLoop} reuseCount:${reuseCount} - ${info.threadName}`);
});
}
Loading
Loading