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

[wasm][mt] throw from blocking wait on JS interop threads #97052

Merged

Conversation

radekdoulik
Copy link
Member

@radekdoulik radekdoulik commented Jan 16, 2024

Also add test

Contributes to #76958

Copy link

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@ghost ghost assigned radekdoulik Jan 16, 2024
@radekdoulik
Copy link
Member Author

The current approach doesn't solve the blocking wait in JS interop, which is then throwing the exception for us too.

[20:37:25] fail: MONO_WASM:    at System.Threading.Monitor.Wait(Object obj, Int32 millisecondsTimeout)
                    at System.Threading.ManualResetEventSlim.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
                    at System.Threading.ManualResetEventSlim.Wait()
                    at System.Runtime.InteropServices.JavaScript.JavaScriptExports.CompleteTask(JSMarshalerArgument* arguments_buffer)
                 Error: blocking Wait is not supported on the JS interop thread.
                     at wr (http://127.0.0.1:42115/_framework/dotnet.runtime.js:3:35092)
                     at Qo (http://127.0.0.1:42115/_framework/dotnet.runtime.js:3:73035)
                     at p.javaScriptExports.complete_task (http://127.0.0.1:42115/_framework/dotnet.runtime.js:3:248198)
                     at http://127.0.0.1:42115/_framework/dotnet.runtime.js:3:80721

We discussed it in chat and agreed on the introduction of a new flag to signal that the wait comes from JS interop code. The flag can be added to the Monitor class and thus simplify the thread JS interop thread detection.

To not mix intree references and source project
This replaces the previous context base and makes it possible to disable
throw for blocking calls in JS interop
@radekdoulik
Copy link
Member Author

New fail to look into:

[16:54:41] info: [2024-01-19T16:54:41.880Z] [FAIL] System.Runtime.InteropServices.JavaScript.Tests.WebWorkerTest.JSSynchronizationContext_Send_Post_Items_Cancellation
[16:54:41] info: Assert.Throws() Failure: Exception type was not an exact match
[16:54:41] info: Expected: typeof(System.OperationCanceledException)
[16:54:41] info: Actual:   typeof(System.ObjectDisposedException)
[16:54:41] info: ---- System.ObjectDisposedException : Cannot access a disposed object.
[16:54:41] info: Object name: 'System.Runtime.InteropServices.JavaScript.JSSynchronizationContext'.
[16:54:41] info:    at System.Runtime.InteropServices.JavaScript.Tests.WebWorkerTest.JSSynchronizationContext_Send_Post_Items_Cancellation()
[16:54:41] info: --- End of stack trace from previous location ---
[16:54:41] info: ----- Inner Stack Trace -----
[16:54:41] info:    at System.Runtime.InteropServices.JavaScript.JSSynchronizationContext.Send(SendOrPostCallback , Object )
[16:54:41] info:    at System.Runtime.InteropServices.JavaScript.Tests.WebWorkerTest.<>c__DisplayClass6_0.<JSSynchronizationContext_Send_Post_Items_Cancellation>b__1()
[16:54:41] info:    at System.Threading.Tasks.Task`1[[System.Threading.Tasks.Task, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].InnerInvoke()
[16:54:41] info:    at System.Threading.Tasks.Task.<>c.<.cctor>b__281_0(Object obj)
[16:54:41] info:    at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread , ExecutionContext , ContextCallback , Object )
[16:54:41] info: --- End of stack trace from previous location ---
[16:54:41] info:    at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread , ExecutionContext , ContextCallback , Object )
[16:54:41] info:    at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& , Thread )
[16:54:41] info: --- End of stack trace from previous location ---

@pavelsavara
Copy link
Member

New fail to look into:

It's unrelated to your PR, please add it to #96628

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@radekdoulik
Copy link
Member Author

/azp run runtime-wasm

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@pavelsavara
Copy link
Member

Log

[16:55:56] fail: [FAIL] System.Runtime.InteropServices.JavaScript.Tests.WebWorkerTest.JSSynchronizationContext_Send_Post_Items_Cancellation
[16:55:56] info: Assert.ThrowsAny() Failure: Exception type was not compatible
[16:55:56] info: Expected: typeof(System.OperationCanceledException)
[16:55:56] info: Actual:   typeof(System.ObjectDisposedException)

This is unrelated.

@pavelsavara
Copy link
Member

image

🎉

@pavelsavara
Copy link
Member

Quick list of APIs, for which we need to validate that they internally use something we already addressed so far.
Or we need to address them too.

  • Task - WaitAll, WaitAny
  • WaitSubsystem - Wait
  • WaitableObject - .Wait, SatisfyWaitForAll, Wait_Locked
  • ThreadWaitInfo - .Wait, Sleep,
  • LowLevelLock - WaitAndAcquire
  • LowLevelMonitor - Wait, Acquire
  • LowLevelSpinWaiter - Wait
  • LowLevelLifoSemaphore - Wait
  • FileSystemWatcher - WaitForChanged
  • GC - WaitForFullGCApproach, WaitForFullGCComplete, WaitForPendingFinalizers
  • CancellationTokenSource - WaitForCallbackToComplete
  • ManualResetEventSlim - Wait
  • SemaphoreSlim - Wait
  • SynchronizationContext - Wait
  • WaitHandle - WaitOne, WaitAll
  • ManualResetEventWithAwaiterSupport - Wait
  • CountdownEvent - Wait
  • Interop.Sys.LowLevelMonitor_TimedWait & SystemNative_LowLevelMonitor_Wait

I'm sure I missed some places.

@radekdoulik
Copy link
Member Author

Lets get this in and I can extend the tests and API coverage in follow up PR.

@@ -77,6 +82,12 @@ public static bool IsEntered(object obj)
public static bool Wait(object obj, int millisecondsTimeout)
{
ArgumentNullException.ThrowIfNull(obj);
#if FEATURE_WASM_THREADS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make helper method for this and localize the message.
The method should be "public" but suppressed same like ThrowOnBlockingWaitOnJSInteropThread.
So that we could use it in other places in the runtime.

@radekdoulik radekdoulik merged commit 9b7aa3d into dotnet:main Feb 1, 2024
192 of 206 checks passed
signal.Wait();
Monitor.ThrowOnBlockingWaitOnJSInteropThread = threadFlag;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be in try-finally ?
could .Wait ever throw ?
@radekdoulik

Copy link
Member

@pavelsavara pavelsavara Feb 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll will change that on my PR #97832

@pavelsavara
Copy link
Member

This is unrelated.

It was actually related but hiding behind another problem.
This is now throwing PNSE (as it should), but the test was not ready for it.

I'm fixing it in #97832

radekdoulik added a commit to radekdoulik/runtime that referenced this pull request Feb 5, 2024
The project files have now diferent dependencies
ViktorHofer added a commit that referenced this pull request Feb 5, 2024
* Update solution files after changes in #97052

The project files have now diferent dependencies

* Update System.Runtime.InteropServices.JavaScript.sln

* Update System.Net.Http.sln

* Update System.Net.WebSockets.Client.sln

---------

Co-authored-by: Viktor Hofer <[email protected]>
@github-actions github-actions bot locked and limited conversation to collaborators Mar 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants