-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
[WASM] dynamically compiled method with infinite loop renders the runtime non-functional #98855
Comments
cc @kg |
Tagging subscribers to this area: @BrzVlad, @kotlarmilos Issue DetailsDescriptionAttempting to execute a dynamically compiled method that contains an infinite loop while (true) { } Results in the runtime becoming non functional. There is an error that appears in the browser console. Any subsequent requests to the runtime fail with the same error.
Full stack trace
Reproduction StepsThe issue can be seen here: https://infinite-loop-dynamic.wasmsharp.pages.dev/ On my machine, it consistently takes ~5 seconds after clicking "Run Code", before the error in the console appears. Expected behaviorThe runtime hangs. Interestingly, this is exactly what happens for a non-dynamically compiled method that includes a Clicking the "Run Code" button ends up with the runtime hanging, with no errors after a a while. Actual behaviorAn error occurs. Taking a memory snapshot in DevTools after the error shows ~2GB of memory requested: However, the actual allocated size of objects says that its much smaller: It does not really make much sense to me. A memory issue might make some sense given that the error stack trace contains Regression?No response Known WorkaroundsNo response Configuration
dotnet --info output |
Author: | JakeYallop |
---|---|
Assignees: | - |
Labels: |
|
Milestone: | - |
Thanks for the report! What is the behavior you expect? An infinite loop isn't going to do anything useful regardless of whether this bug is present, so I assume this is a reduced version of a problem in application code where you have a long or infinite loop that does actual work, but isn't behaving correctly. You also mention a web worker, which won't be present in the default configuration of the .NET runtime. Are you using a multithreaded build from source? Our default configuration is single-threaded. From 'Interestingly, this is exactly what happens for a non-dynamically compiled method that includes a while (true) { } loop.' it sounds like loops are not behaving to your satisfaction in both scenarios, but this report is for dynamic compilation because it produces a unique error. Is that correct? |
From looking at the stack trace and related code, it seems like this is a straightforward out-of-memory condition involving (but not necessarily caused by) the interpreter. As a basic check, are you certain you're not accidentally dynamically compiling a bunch of methods? The failed allocation in that stack is the creation of a memory pool, and we usually create one of those for each method transformed by the interpreter. So for that allocation to fail, we would have to start doing interpreter codegen after we've already allocated a ton of memory (likely the 2GB you see in that snapshot). Does your application usually allocate that much memory under normal circumstances? Each dynamically compiled method will use up memory for interpreter internals and potentially for jiterpreter traces as well, and most of that memory will be a part of the WASM heap, so it won't show up as individual allocations in chrome's devtools, it's one big block. I did some local testing and was not able to reproduce this, but if you let me know more about how you're dynamically compiling this method (sample IL, etc) I can try to reproduce this here and investigate further. |
I totally agree that an infinite loop is not going to do anything useful, I was just interested in what would actually happen, so in this case its not a reduction of a problem. I'm kind of okay if we just want to close this, but it does seem like odd behaviour, as I wouldn't expect an empty while loop to do anything other than hang. As mentioned above, adding an empty while loop in my compiled code does exactly that - nothing at all, the runtime hangs as expected and memory usage does not grow.
I'm not using the multithreaded runtime - instead I'm just loading the runtime myself inside a web worker, https://github.com/JakeYallop/WasmSharp/blob/main/packages/core/src/worker.ts
Did you try the link in the original issue, at least as a sense check it would good to know that its not just me 😄. https://infinite-loop-dynamic.wasmsharp.pages.dev/ - I know its not super useful in practice due to the difficulty in debugging.
No, it does not - its very obvious just from looking at Task Manager - as soon as I run the repro, the memory usage that my web browser is using explodes. Normal memory usage for the app is very low (it basically doesn't do much right now anyway)
I'm actually compiling the code using Roslyn, then using |
It does allocate 2GB and then fail for me when I load your webpage and click Run Code, yes. I'm guessing this prefilled snippet from your sample is the repro case? using System;
using System.Reflection.Emit;
//or remove the return to use the code below
var method = new DynamicMethod("Test", typeof(void), Array.Empty<Type>());
ILGenerator il = method.GetILGenerator(32);
var loopTarget = il.DefineLabel();
il.MarkLabel(loopTarget);
il.Emit(OpCodes.Br_S, loopTarget);
var MyMethod = method.CreateDelegate<InfiniteLoop>();
MyMethod();
delegate void InfiniteLoop(); If so, I'll do some testing with it later today. Alternately, you can provide the resulting assembly that Roslyn compiled, but this seems like a pretty straightforward snippet and is roughly what I had in mind. |
Actually, it reproduces with just while (true) { } as code, no manual IL generation needed. Although I assume |
Thanks, that is helpful. It doesn't reproduce in a local build of .NET 9, so it's possible we already fixed it with recent changes to the interpreter, but I'll dig in a little more. If you find ways to reproduce this against 8 with production code do let us know. |
Description
Attempting to execute a dynamically compiled method that contains an infinite loop
Results in the runtime becoming non functional. There is an error that appears in the browser console. Any subsequent requests to the runtime fail with the same error.
Full stack trace
Reproduction Steps
The issue can be seen here:
https://infinite-loop-dynamic.wasmsharp.pages.dev/
On my machine, it consistently takes ~5 seconds after clicking "Run Code", before the error in the console appears.
Expected behavior
The runtime hangs.
Interestingly, this is exactly what happens for a non-dynamically compiled method that includes a
while (true) { }
loop. https://infinite-loop-precompiled.wasmsharp.pages.dev/ has a loop inserted into the run method:https://github.com/JakeYallop/WasmSharp/blob/infinite-loop-in-run/packages/core/src/Services/CodeSession.cs#L149
Clicking the "Run Code" button ends up with the runtime hanging, with no errors after a a while.
Actual behavior
An error occurs.
Taking a memory snapshot in DevTools after the error shows ~2GB of memory requested:

However, the actual allocated size of objects says that its much smaller:

It does not really make much sense to me.
A memory issue might make some sense given that the error stack trace contains
/__w/1/s/src/mono/mono/eglib/gmem.c:123
.Regression?
No response
Known Workarounds
No response
Configuration
Full
dotnet --info
outputOther information
The runtime is running from inside a web worker.
The text was updated successfully, but these errors were encountered: