Skip to content

Commit d0023cf

Browse files
pavelsavaramaraf
andauthored
[browser][MT] assert no managed transition on UI thread after start (#100410)
Co-authored-by: Marek Fišera <[email protected]>
1 parent 8618814 commit d0023cf

File tree

8 files changed

+27
-8
lines changed

8 files changed

+27
-8
lines changed

src/mono/browser/runtime/exports-internal.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ export function cwraps_internal (internal: any): void {
127127

128128
/* @deprecated not GC safe, legacy support for Blazor */
129129
export function monoObjectAsBoolOrNullUnsafe (obj: MonoObject): boolean | null {
130+
// TODO https://github.com/dotnet/runtime/issues/100411
131+
// after Blazor stops using monoObjectAsBoolOrNullUnsafe
132+
130133
if (obj === MonoObjectNull) {
131134
return null;
132135
}

src/mono/browser/runtime/gc-lock.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import cwraps from "./cwraps";
77

88
export let gc_locked = false;
99

10+
// TODO https://github.com/dotnet/runtime/issues/100411
11+
// after Blazor stops using mono_wasm_gc_lock, mono_wasm_gc_unlock
12+
1013
export function mono_wasm_gc_lock (): void {
1114
if (gc_locked) {
1215
throw new Error("GC is already locked");

src/mono/browser/runtime/marshal-to-cs.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import { _zero_region, localHeapViewF64, localHeapViewI32, localHeapViewU8 } fro
2222
import { stringToMonoStringRoot, stringToUTF16 } from "./strings";
2323
import { JSMarshalerArgument, JSMarshalerArguments, JSMarshalerType, MarshalerToCs, MarshalerToJs, BoundMarshalerToCs, MarshalerType } from "./types/internal";
2424
import { TypedArray } from "./types/emscripten";
25-
import { gc_locked } from "./gc-lock";
2625

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

@@ -224,6 +223,7 @@ function _marshal_string_to_cs_impl (arg: JSMarshalerArgument, value: string) {
224223
set_arg_intptr(arg, buffer);
225224
set_arg_length(arg, value.length);
226225
} else {
226+
mono_assert(!WasmEnableThreads, "Marshaling strings by reference is not supported in multithreaded mode");
227227
const root = get_string_root(arg);
228228
try {
229229
stringToMonoStringRoot(value, root);
@@ -463,7 +463,7 @@ export function marshal_array_to_cs_impl (arg: JSMarshalerArgument, value: Array
463463
mono_check(Array.isArray(value), "Value is not an Array");
464464
_zero_region(buffer_ptr, buffer_length);
465465
if (!WasmEnableJsInteropByValue) {
466-
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when creating a GC root");
466+
mono_assert(!WasmEnableThreads, "Marshaling strings by reference is not supported in multithreaded mode");
467467
cwraps.mono_wasm_register_root(buffer_ptr, buffer_length, "marshal_array_to_cs");
468468
}
469469
for (let index = 0; index < length; index++) {
@@ -474,7 +474,7 @@ export function marshal_array_to_cs_impl (arg: JSMarshalerArgument, value: Array
474474
mono_check(Array.isArray(value), "Value is not an Array");
475475
_zero_region(buffer_ptr, buffer_length);
476476
if (!WasmEnableJsInteropByValue) {
477-
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when creating a GC root");
477+
mono_assert(!WasmEnableThreads, "Marshaling objects by reference is not supported in multithreaded mode");
478478
cwraps.mono_wasm_register_root(buffer_ptr, buffer_length, "marshal_array_to_cs");
479479
}
480480
for (let index = 0; index < length; index++) {

src/mono/browser/runtime/marshal-to-js.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import { TypedArray } from "./types/emscripten";
2222
import { get_marshaler_to_cs_by_type, jsinteropDoc, marshal_exception_to_cs } from "./marshal-to-cs";
2323
import { localHeapViewF64, localHeapViewI32, localHeapViewU8 } from "./memory";
2424
import { call_delegate } from "./managed-exports";
25-
import { gc_locked } from "./gc-lock";
2625
import { mono_log_debug } from "./logging";
2726
import { invoke_later_when_on_ui_thread_async } from "./invoke-js";
2827

@@ -390,6 +389,7 @@ export function marshal_string_to_js (arg: JSMarshalerArgument): string | null {
390389
Module._free(buffer as any);
391390
return value;
392391
} else {
392+
mono_assert(!WasmEnableThreads, "Marshaling strings by reference is not supported in multithreaded mode");
393393
const root = get_string_root(arg);
394394
try {
395395
const value = monoStringToString(root);
@@ -504,7 +504,7 @@ function _marshal_array_to_js_impl (arg: JSMarshalerArgument, element_type: Mars
504504
result[index] = marshal_string_to_js(element_arg);
505505
}
506506
if (!WasmEnableJsInteropByValue) {
507-
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when disposing a GC root");
507+
mono_assert(!WasmEnableThreads, "Marshaling string by reference is not supported in multithreaded mode");
508508
cwraps.mono_wasm_deregister_root(<any>buffer_ptr);
509509
}
510510
} else if (element_type == MarshalerType.Object) {
@@ -514,7 +514,7 @@ function _marshal_array_to_js_impl (arg: JSMarshalerArgument, element_type: Mars
514514
result[index] = _marshal_cs_object_to_js(element_arg);
515515
}
516516
if (!WasmEnableJsInteropByValue) {
517-
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when disposing a GC root");
517+
mono_assert(!WasmEnableThreads, "Marshaling objects by reference is not supported in multithreaded mode");
518518
cwraps.mono_wasm_deregister_root(<any>buffer_ptr);
519519
}
520520
} else if (element_type == MarshalerType.JSObject) {

src/mono/browser/runtime/roots.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import WasmEnableThreads from "consts:wasmEnableThreads";
55

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

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

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

7275
if (_scratch_root_free_instances.length > 0) {

src/mono/browser/runtime/startup.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,14 +288,16 @@ async function onRuntimeInitializedAsync (userOnRuntimeInitialized: () => void)
288288
runtimeHelpers.ioThreadTID = tcwraps.mono_wasm_create_io_thread();
289289
}
290290

291-
// TODO make UI thread not managed
291+
// TODO make UI thread not managed/attached https://github.com/dotnet/runtime/issues/100411
292292
tcwraps.mono_wasm_register_ui_thread();
293293
monoThreadInfo.isAttached = true;
294294
monoThreadInfo.isRegistered = true;
295295

296296
runtimeHelpers.runtimeReady = true;
297297
update_thread_info();
298298
bindings_init();
299+
300+
runtimeHelpers.disableManagedTransition = true;
299301
} else {
300302
// load mono runtime and apply environment settings (if necessary)
301303
await start_runtime();

src/mono/browser/runtime/strings.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
import WasmEnableThreads from "consts:wasmEnableThreads";
5+
46
import { mono_wasm_new_root, mono_wasm_new_root_buffer } from "./roots";
57
import { MonoString, MonoStringNull, WasmRoot, WasmRootBuffer } from "./types/internal";
68
import { Module } from "./globals";
@@ -118,6 +120,10 @@ export function stringToUTF16Ptr (str: string): VoidPtr {
118120
}
119121

120122
export function monoStringToString (root: WasmRoot<MonoString>): string | null {
123+
// TODO https://github.com/dotnet/runtime/issues/100411
124+
// after Blazor stops using monoStringToStringUnsafe
125+
// mono_assert(!WasmEnableThreads, "Marshaling strings by reference is not supported in multithreaded mode");
126+
121127
if (root.value === MonoStringNull)
122128
return null;
123129

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

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

157164
if (string === null)

src/mono/browser/runtime/types/internal.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ export type RuntimeHelpers = {
206206
getMemory(): WebAssembly.Memory,
207207
getWasmIndirectFunctionTable(): WebAssembly.Table,
208208
runtimeReady: boolean,
209+
disableManagedTransition: boolean,
209210
monoThreadInfo: PThreadInfo,
210211
proxyGCHandle: GCHandle | undefined,
211212
managedThreadTID: PThreadPtr,

0 commit comments

Comments
 (0)