dotnet / dotnet/project-system
Eliminate _pendingSessionState from ProjectHotReloadSessionManager
- Dominant language
- C#
- Stars
- 1k
- Forks
- 415
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
`ProjectHotReloadSessionManager` holds a `_pendingSessionState` to hold and track the current pending session during launching debugtarget, which is easy to cause race condition.
## how hotreload setup generally
- hotreload client runs in tooling process, it sends payload to application agent
- application agent runs in dotnet host, it receives payload from hotreload client and applies to application assembly.
- hotreload client and application agent communicate via named pipe
- hotreload client starts the named pipe server, applies the pipe name to environment variable when launching application and waits for connection from application agent.
- application agent in dotnet host will connect to the named pipe stream and sending its capability to the hotreload client. Then it waits for another completion signal from hotreload client.
- once hotreload client received the connection, it will send the completion signal to the application agent.
- dotnet host continue to start application.
## How project system starts user application
The project system splits the project launching process into three stages
- QueryDebugTargetsAsync
- Launch DebugTargets using debugger API
- OnAfterLaunchAsync with launched process information, like pid, for final setup
## how hotreload setup in project system using `ProjectHotReloadSessionManager`
- In QueryDebugTargetsAsync, `ProjectHotReloadSessionManager.TryCreatePendingSessionAsync` get invoked. It [starts the named pipe server, applies the pipe name to launch variables](https://github.com/dotnet/project-system/blob/18310492abb9419e1f7b061ac151d97492da261c/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/HotReload/ProjectHotReloadSessionManager.cs#L87) and save the pending state in `_pendingSessionState`
- The `_pendingSessionState` remains to track the pending session during launching DebugTargets
- In `OnAfterLaunchAsync`, `ProjectHotReloadSessionManager` complete the hotreload session setup by calling `ActivateSessionAsync` with `_pendingSessionState`, where it sends the completion signal to application host so application can continue to start, register hotreload session to debugger and also listen from the process exit event to correctly unregistered hotreload session from debugger when process exit.
## Potential racing condition in the hotreload setup process
The major risk is introduced by holding `_pendingSessionState` across several async methods, which might be invoked in uncertain order and uncertain times.
## Eliminate `_pendingSessionState` as state sharing across several async methods during project launching.
One way to eliminate `_pendingSessionState` without changing existing contract could be use named pipe as pending Session State ID and track them in `Dictionary _pendingSessionState`. Because named pipe is injected in process launching environment variables, it can be retrieved in both `QueryDebugTargetsAsync` and `OnAfterLaunchAsync`. So that we can still sync on the ongoing hotreload setup process without `_pendingSessionState`
Another way could be using dataflow. Need to discuss on how to set it up.
## User Impact
Contributor guide
Assessment
This issue has not been assessed yet.