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] ENVIRONMENT_IS_WEB is false when dotnet started on worker, leads to exit(0) #91528

Closed
Tarun047 opened this issue Sep 4, 2023 · 8 comments · Fixed by #91589
Closed
Assignees
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript os-browser Browser variant of arch-wasm
Milestone

Comments

@Tarun047
Copy link
Contributor

Tarun047 commented Sep 4, 2023

Description

Hi,
I am facing a weird crash when using .NET 8 Latest Preview for targeting WASM Browser (AOT build).
The bug is observed in the following conditions.
The bug came out while benchmarking the performance of JS and .NET AOT Wasm.
When running a React Application, that uses web workers.
The idea is to let user select a file and to compress it using .NET WASM code.
Because this is a heavy task, a web worker is used to delegate the task to .NET WASM compression layer.
The Web App works fine with small files < 5MB.
But If we chose to go with larger files, the compression still succeeds (ofc until we hit OOM) but the .NET runtime exits abruptly with the following weird stack trace if we use files >10MB

Reproduction Steps

A repository to reproduce the issue is can he found here dotnet-wasm-react.

Inorder to reproduce this issue,

  1. Have the .NET 8.0.100-preview.7.23376.3 SDK and also install the wasm-tools, wasm-experimental workloads.

  2. Checkout the repository and perform the following actions:
    Publish the compress.csproj by running
    dotnet publish -c Release
    Copy the outputs of /bin/Release/net8.0/browser-wasm/AppBundle/ to compressy-frontend/public/vendor

  3. From the compressy-frontend folder,
    Install npm dependencies by running npm install and start the webpack dev server by running npm run dev

  4. Use a browser and navigate to http://localhost:8080 and keep the browser console window in browser dev tools open select the choose file button next to WASM .NET Compress and select any large file (>10MB preferably) in file chooser.

  5. check the console output for failure stack trace.

Expected behavior

The .NET WASM AOT runtime does not abruptly exit.

Actual behavior

The .NET WASM AOT Run time exits with following weird stack trace which I suspect is due to a possible stack corruption.

[Error] MONO_WASM: {"name":"ExitStatus","message":"Program terminated with exit(undefined)","stack":
"H@http://localhost:8080/vendor/_framework/dotnet.js:3:9846
@http://localhost:8080/vendor/_framework/dotnet.runtime.js:3:203721
_proc_exit@http://localhost:8080/vendor/_framework/dotnet.native.js:8:73946
exitJS@http://localhost:8080/vendor/_framework/dotnet.native.js:8:74058
maybeExit@http://localhost:8080/vendor/_framework/dotnet.native.js:8:89407
Ko@http://localhost:8080/vendor/_framework/dotnet.runtime.js:3:56101
callUserCallback@http://localhost:8080/vendor/_framework/dotnet.native.js:8:89507
@http://localhost:8080/vendor/_framework/dotnet.native.js:8:89634","silent":true}
	l (dotnet.js:3:673)
	(anonymous function) (dotnet.js:3:10723)
	H (dotnet.js:3:10910)
	(anonymous function) (dotnet.runtime.js:3:203722)
	_proc_exit (dotnet.native.js:8:73947)
	exitJS (dotnet.native.js:8:74059)
	maybeExit (dotnet.native.js:8:89408)
	Ko (dotnet.runtime.js:3:56102)
	callUserCallback (dotnet.native.js:8:89508)
	(anonymous function) (dotnet.native.js:8:89635)

Regression?

The issue doesn't happen in .NET 7 WASM AOT builds

Known Workarounds

I haven't found a way to make this work

Configuration

Version: .NET 8.0.100-preview.7.23376.3
OS: Reproducible on Mac OS X, Windows.
Architecture: ARM64, X64
Browsers: Safari, Firefox, Chrome

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 4, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Sep 4, 2023
@Tarun047
Copy link
Contributor Author

Tarun047 commented Sep 4, 2023

@pavelsavara please help

@jkotas jkotas added the arch-wasm WebAssembly architecture label Sep 4, 2023
@ghost
Copy link

ghost commented Sep 4, 2023

Tagging subscribers to 'arch-wasm': @lewing
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Hi,
I am facing a weird crash when using .NET 8 Latest Preview for targeting WASM Browser (AOT build).
The bug is observed in the following conditions.
The bug came out while benchmarking the performance of JS and .NET AOT Wasm.
When running a React Application, that uses web workers.
The idea is to let user select a file and to compress it using .NET WASM code.
Because this is a heavy task, a web worker is used to delegate the task to .NET WASM compression layer.
The Web App works fine with small files < 5MB.
But If we chose to go with larger files, the compression still succeeds (ofc until we hit OOM) but the .NET runtime exits abruptly with the following weird stack trace if we use files >10MB

Reproduction Steps

A repository to reproduce the issue is can he found here dotnet-wasm-react.

Inorder to reproduce this issue,

  1. Have the .NET 8.0.100-preview.7.23376.3 SDK and also install the wasm-tools, wasm-experimental workloads.

  2. Checkout the repository and perform the following actions:
    Publish the compress.csproj by running
    dotnet publish -c Release
    Copy the outputs of /bin/Release/net8.0/browser-wasm/AppBundle/ to compressy-frontend/public/vendor

  3. From the compressy-frontend folder,
    Install npm dependencies by running npm install and start the webpack dev server by running npm run dev

  4. Use a browser and navigate to http://localhost:8080 and keep the browser console window in browser dev tools open select the choose file button next to WASM .NET Compress and select any large file (>10MB preferably) in file chooser.

  5. check the console output for failure stack trace.

Expected behavior

The .NET WASM AOT runtime does not abruptly exit.

Actual behavior

The .NET WASM AOT Run time exits with following weird stack trace which I suspect is due to a possible stack corruption.

[Error] MONO_WASM: {"name":"ExitStatus","message":"Program terminated with exit(undefined)","stack":"H@http://localhost:8080/vendor/_framework/dotnet.js:3:9846\n@http://localhost:8080/vendor/_framework/dotnet.runtime.js:3:203721\n_proc_exit@http://localhost:8080/vendor/_framework/dotnet.native.js:8:73946\nexitJS@http://localhost:8080/vendor/_framework/dotnet.native.js:8:74058\nmaybeExit@http://localhost:8080/vendor/_framework/dotnet.native.js:8:89407\nKo@http://localhost:8080/vendor/_framework/dotnet.runtime.js:3:56101\ncallUserCallback@http://localhost:8080/vendor/_framework/dotnet.native.js:8:89507\n@http://localhost:8080/vendor/_framework/dotnet.native.js:8:89634","silent":true}
	l (dotnet.js:3:673)
	(anonymous function) (dotnet.js:3:10723)
	H (dotnet.js:3:10910)
	(anonymous function) (dotnet.runtime.js:3:203722)
	_proc_exit (dotnet.native.js:8:73947)
	exitJS (dotnet.native.js:8:74059)
	maybeExit (dotnet.native.js:8:89408)
	Ko (dotnet.runtime.js:3:56102)
	callUserCallback (dotnet.native.js:8:89508)
	(anonymous function) (dotnet.native.js:8:89635)

Regression?

The issue doesn't happen in .NET 7 WASM AOT builds

Known Workarounds

I haven't found a way to make this work

Configuration

Version: .NET 8.0.100-preview.7.23376.3
OS: Reproducible on Mac OS X, Windows.
Architecture: ARM64, X64
Browsers: Safari, Firefox, Chrome

Other information

No response

Author: Tarun047
Assignees: -
Labels:

arch-wasm, untriaged, needs-area-label

Milestone: -

@jkotas jkotas added area-Codegen-meta-mono and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 4, 2023
@pavelsavara
Copy link
Member

pavelsavara commented Sep 4, 2023

We need to narrow the scope of the problem. I suggest that you start with

  1. try to reproduce the issue without web worker
  2. try to reproduce the issue without AOT
  3. compile with debug symbols and catch the exception in dev tools debugger (and see better stack trace)
<PropertyGroup>
  <WasmNativeDebugSymbols>true</WasmNativeDebugSymbols>
  <WasmNativeStrip>false</WasmNativeStrip>
</PropertyGroup>
  1. try larger wasm stack size with
<PropertyGroup>
  <EmccStackSize>50MB</EmccStackSize>
</PropertyGroup>
  1. try to disable jiterp
<PropertyGroup>
   <BlazorWebAssemblyJiterpreter>false</BlazorWebAssemblyJiterpreter>
</PropertyGroup>

Please let us know what have you found out.

@pavelsavara pavelsavara self-assigned this Sep 4, 2023
@pavelsavara pavelsavara added this to the 8.0.0 milestone Sep 4, 2023
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Sep 4, 2023
@pavelsavara pavelsavara added untriaged New issue has not been triaged by the area owner os-browser Browser variant of arch-wasm needs-author-action An issue or pull request that requires more info or actions from the author. and removed untriaged New issue has not been triaged by the area owner labels Sep 4, 2023
@ghost
Copy link

ghost commented Sep 4, 2023

This issue has been marked needs-author-action and may be missing some important information.

@Tarun047
Copy link
Contributor Author

Tarun047 commented Sep 4, 2023

@pavelsavara
I have reproduced the scenarios you've requested

  1. Without Web Worker - Not able to reproduce (But I don't think this would be a viable workaround, because CPU intensive tasks aren't meant to run on main thread)
    Code Tested

  2. Web Worker Without AOT - Runtime exits abruptly, stack trace attached
    crash-disable-aot.log
    Code Tested

  3. Web Worker With Debugging Symbols - Runtime exits abruptly, attached stack trace below
    crash-error.log
    Code Tested

  4. Web Worker with Increased Initial Heap Size and Stack Size - Runtime exits abruptly, had to also increase initial heap size due to build error. Stack trace attached.
    crash-log-with-increased-stack-size.log
    Code Tested

  5. Web Worker Without AOT Without BlazorJiterpreter - Runtime exits abruptly, stack
    disable-jiterp.log
    Code Tested

@ghost ghost added needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration and removed needs-author-action An issue or pull request that requires more info or actions from the author. labels Sep 4, 2023
@pavelsavara
Copy link
Member

@Tarun047 , thanks for the help.

The issue is that whet dotnet is started on the worker, it thinks that it's not running on a browser and therefore will exit(0) after last promise is fulfilled.

I will think about proper fix for this situation, but for now, the workaround is to set window in the worker, before you call dotnet.create in your main.js

globalThis.window = globalThis;
return dotnet.create();

As I worked with your sample app I noticed few things. These are just hints for you, not relevant to this dotnet issue. Feel free to ignore it, if this is just simple throw away sample app.

  • your react useEffect is creating the worker multiple times. You probably want to create just one and return cleanup function from it, to unregister from worker's onmessage when the component unmounts.
  • you should await initializeRuntimeExports and createRuntime functions before calling nativeCompress. This could be done with top-level await in native-worker.ts

@Tarun047
Copy link
Contributor Author

Tarun047 commented Sep 5, 2023

Just curious about this,
How come the runtime doesn't exit when I upload small files (< 5MB) ?
Asking this because I am able to do multiple uploads for small files.

Also one more observation is that when I do memoryStream.GetBuffer() instead of memoryStream.ToArray() in C#
it doesn't exit the runtime, which seems odd to me.

@pavelsavara pavelsavara changed the title Unexpected crash in Browser WASM (Possible Stack Corruption) [browser] ENVIRONMENT_IS_WEB is false when dotnet started on worker, leads to exit(0) Sep 5, 2023
@pavelsavara pavelsavara added area-System.Runtime.InteropServices.JavaScript and removed needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration area-Codegen-meta-mono labels Sep 5, 2023
@pavelsavara
Copy link
Member

Just curious about this, How come the worker doesn't exit when I upload small files (< 5MB) ? Asking this because I am able to do multiple uploads for small files.

I think that it can process it synchronously or that GC is not scheduled (on worker's timer loop). The maybeExit is called after (any) timer callback

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Sep 5, 2023
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Sep 5, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Oct 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript os-browser Browser variant of arch-wasm
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants