Skip to content

Commit

Permalink
[browser][MT] assert no managed transition on UI thread after start (d…
Browse files Browse the repository at this point in the history
…otnet#100410)

Co-authored-by: Marek Fišera <[email protected]>
  • Loading branch information
2 people authored and matouskozak committed Apr 30, 2024
1 parent 54c597f commit 35aff5d
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 8 deletions.
3 changes: 3 additions & 0 deletions src/mono/browser/runtime/exports-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ export function cwraps_internal (internal: any): void {

/* @deprecated not GC safe, legacy support for Blazor */
export function monoObjectAsBoolOrNullUnsafe (obj: MonoObject): boolean | null {
// TODO https://github.com/dotnet/runtime/issues/100411
// after Blazor stops using monoObjectAsBoolOrNullUnsafe

if (obj === MonoObjectNull) {
return null;
}
Expand Down
3 changes: 3 additions & 0 deletions src/mono/browser/runtime/gc-lock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import cwraps from "./cwraps";

export let gc_locked = false;

// TODO https://github.com/dotnet/runtime/issues/100411
// after Blazor stops using mono_wasm_gc_lock, mono_wasm_gc_unlock

export function mono_wasm_gc_lock (): void {
if (gc_locked) {
throw new Error("GC is already locked");
Expand Down
6 changes: 3 additions & 3 deletions src/mono/browser/runtime/marshal-to-cs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { _zero_region, localHeapViewF64, localHeapViewI32, localHeapViewU8 } fro
import { stringToMonoStringRoot, stringToUTF16 } from "./strings";
import { JSMarshalerArgument, JSMarshalerArguments, JSMarshalerType, MarshalerToCs, MarshalerToJs, BoundMarshalerToCs, MarshalerType } from "./types/internal";
import { TypedArray } from "./types/emscripten";
import { gc_locked } from "./gc-lock";

export const jsinteropDoc = "For more information see https://aka.ms/dotnet-wasm-jsinterop";

Expand Down Expand Up @@ -224,6 +223,7 @@ function _marshal_string_to_cs_impl (arg: JSMarshalerArgument, value: string) {
set_arg_intptr(arg, buffer);
set_arg_length(arg, value.length);
} else {
mono_assert(!WasmEnableThreads, "Marshaling strings by reference is not supported in multithreaded mode");
const root = get_string_root(arg);
try {
stringToMonoStringRoot(value, root);
Expand Down Expand Up @@ -463,7 +463,7 @@ export function marshal_array_to_cs_impl (arg: JSMarshalerArgument, value: Array
mono_check(Array.isArray(value), "Value is not an Array");
_zero_region(buffer_ptr, buffer_length);
if (!WasmEnableJsInteropByValue) {
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when creating a GC root");
mono_assert(!WasmEnableThreads, "Marshaling strings by reference is not supported in multithreaded mode");
cwraps.mono_wasm_register_root(buffer_ptr, buffer_length, "marshal_array_to_cs");
}
for (let index = 0; index < length; index++) {
Expand All @@ -474,7 +474,7 @@ export function marshal_array_to_cs_impl (arg: JSMarshalerArgument, value: Array
mono_check(Array.isArray(value), "Value is not an Array");
_zero_region(buffer_ptr, buffer_length);
if (!WasmEnableJsInteropByValue) {
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when creating a GC root");
mono_assert(!WasmEnableThreads, "Marshaling objects by reference is not supported in multithreaded mode");
cwraps.mono_wasm_register_root(buffer_ptr, buffer_length, "marshal_array_to_cs");
}
for (let index = 0; index < length; index++) {
Expand Down
6 changes: 3 additions & 3 deletions src/mono/browser/runtime/marshal-to-js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { TypedArray } from "./types/emscripten";
import { get_marshaler_to_cs_by_type, jsinteropDoc, marshal_exception_to_cs } from "./marshal-to-cs";
import { localHeapViewF64, localHeapViewI32, localHeapViewU8 } from "./memory";
import { call_delegate } from "./managed-exports";
import { gc_locked } from "./gc-lock";
import { mono_log_debug } from "./logging";
import { invoke_later_when_on_ui_thread_async } from "./invoke-js";

Expand Down Expand Up @@ -390,6 +389,7 @@ export function marshal_string_to_js (arg: JSMarshalerArgument): string | null {
Module._free(buffer as any);
return value;
} else {
mono_assert(!WasmEnableThreads, "Marshaling strings by reference is not supported in multithreaded mode");
const root = get_string_root(arg);
try {
const value = monoStringToString(root);
Expand Down Expand Up @@ -504,7 +504,7 @@ function _marshal_array_to_js_impl (arg: JSMarshalerArgument, element_type: Mars
result[index] = marshal_string_to_js(element_arg);
}
if (!WasmEnableJsInteropByValue) {
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when disposing a GC root");
mono_assert(!WasmEnableThreads, "Marshaling string by reference is not supported in multithreaded mode");
cwraps.mono_wasm_deregister_root(<any>buffer_ptr);
}
} else if (element_type == MarshalerType.Object) {
Expand All @@ -514,7 +514,7 @@ function _marshal_array_to_js_impl (arg: JSMarshalerArgument, element_type: Mars
result[index] = _marshal_cs_object_to_js(element_arg);
}
if (!WasmEnableJsInteropByValue) {
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when disposing a GC root");
mono_assert(!WasmEnableThreads, "Marshaling objects by reference is not supported in multithreaded mode");
cwraps.mono_wasm_deregister_root(<any>buffer_ptr);
}
} else if (element_type == MarshalerType.JSObject) {
Expand Down
5 changes: 4 additions & 1 deletion src/mono/browser/runtime/roots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import WasmEnableThreads from "consts:wasmEnableThreads";

import cwraps from "./cwraps";
import { Module, mono_assert } from "./globals";
import { Module, mono_assert, runtimeHelpers } from "./globals";
import { VoidPtr, ManagedPointer, NativePointer } from "./types/emscripten";
import { MonoObjectRef, MonoObjectRefNull, MonoObject, is_nullish, WasmRoot, WasmRootBuffer } from "./types/internal";
import { _zero_region, localHeapViewU32 } from "./memory";
Expand All @@ -24,6 +24,7 @@ const _external_root_free_instances: WasmExternalRoot<any>[] = [];
* For small numbers of roots, it is preferable to use the mono_wasm_new_root and mono_wasm_new_roots APIs instead.
*/
export function mono_wasm_new_root_buffer (capacity: number, name?: string): WasmRootBuffer {
if (WasmEnableThreads && runtimeHelpers.disableManagedTransition) throw new Error("External roots are not supported when threads are enabled");
if (capacity <= 0)
throw new Error("capacity >= 1");

Expand All @@ -44,6 +45,7 @@ export function mono_wasm_new_root_buffer (capacity: number, name?: string): Was
* Releasing this root will not de-allocate the root space. You still need to call .release().
*/
export function mono_wasm_new_external_root<T extends MonoObject> (address: VoidPtr | MonoObjectRef): WasmRoot<T> {
if (WasmEnableThreads && runtimeHelpers.disableManagedTransition) throw new Error("External roots are not supported in multithreaded mode");
let result: WasmExternalRoot<T>;

if (!address)
Expand All @@ -67,6 +69,7 @@ export function mono_wasm_new_external_root<T extends MonoObject> (address: Void
* When you are done using the root you must call its .release() method.
*/
export function mono_wasm_new_root<T extends MonoObject> (value: T | undefined = undefined): WasmRoot<T> {
if (WasmEnableThreads && runtimeHelpers.disableManagedTransition) throw new Error("External roots are not supported in multithreaded mode");
let result: WasmRoot<T>;

if (_scratch_root_free_instances.length > 0) {
Expand Down
4 changes: 3 additions & 1 deletion src/mono/browser/runtime/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,14 +288,16 @@ async function onRuntimeInitializedAsync (userOnRuntimeInitialized: () => void)
runtimeHelpers.ioThreadTID = tcwraps.mono_wasm_create_io_thread();
}

// TODO make UI thread not managed
// TODO make UI thread not managed/attached https://github.com/dotnet/runtime/issues/100411
tcwraps.mono_wasm_register_ui_thread();
monoThreadInfo.isAttached = true;
monoThreadInfo.isRegistered = true;

runtimeHelpers.runtimeReady = true;
update_thread_info();
bindings_init();

runtimeHelpers.disableManagedTransition = true;
} else {
// load mono runtime and apply environment settings (if necessary)
await start_runtime();
Expand Down
7 changes: 7 additions & 0 deletions src/mono/browser/runtime/strings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import WasmEnableThreads from "consts:wasmEnableThreads";

import { mono_wasm_new_root, mono_wasm_new_root_buffer } from "./roots";
import { MonoString, MonoStringNull, WasmRoot, WasmRootBuffer } from "./types/internal";
import { Module } from "./globals";
Expand Down Expand Up @@ -118,6 +120,10 @@ export function stringToUTF16Ptr (str: string): VoidPtr {
}

export function monoStringToString (root: WasmRoot<MonoString>): string | null {
// TODO https://github.com/dotnet/runtime/issues/100411
// after Blazor stops using monoStringToStringUnsafe
// mono_assert(!WasmEnableThreads, "Marshaling strings by reference is not supported in multithreaded mode");

if (root.value === MonoStringNull)
return null;

Expand Down Expand Up @@ -152,6 +158,7 @@ export function monoStringToString (root: WasmRoot<MonoString>): string | null {
}

export function stringToMonoStringRoot (string: string, result: WasmRoot<MonoString>): void {
if (WasmEnableThreads) return;
result.clear();

if (string === null)
Expand Down
1 change: 1 addition & 0 deletions src/mono/browser/runtime/types/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export type RuntimeHelpers = {
getMemory(): WebAssembly.Memory,
getWasmIndirectFunctionTable(): WebAssembly.Table,
runtimeReady: boolean,
disableManagedTransition: boolean,
monoThreadInfo: PThreadInfo,
proxyGCHandle: GCHandle | undefined,
managedThreadTID: PThreadPtr,
Expand Down

0 comments on commit 35aff5d

Please sign in to comment.