godotengine / godotengine/godot

`await` generates invalid state machine that never completes for `System.Net.Http.HttpClient`

Open
#91,608 2 comments 0 reactions 0 assignees View on GitHub
bug topic:dotnet topic:network
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

v4.2.1.stable.mono.official [b09f793f5], v4.2.2.stable.mono.official [15073afe3]

### System information

Godot v4.2.2.stable.mono - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4090 (NVIDIA; 31.0.15.5161) - AMD Ryzen 9 5950X 16-Core Processor (32 Threads)

### Issue description

`await` generates an invalid state machine that never completes for `System.Net.Http.HttpClient`
awaiting using .Wait() works as intended.

This is an issue with third-party libraries that use System HttpClient instead of Godot's HttpClient.

### Steps to reproduce

Create a new C# project
Import the code below and run with debugger on (see gif below for execution results)
```csharp
using System.Threading.Tasks;
using Godot;

public partial class TestScript : Node
{
private System.Net.Http.HttpClient _httpClient = new System.Net.Http.HttpClient();

public override void _Ready()
{
Works();
Hangs().Wait();
base._Ready();
}

public void Works()
{
var task = _httpClient.GetAsync("https://www.google.com");
task.Wait();
var google = task.Result;
var contentTask = google.Content.ReadAsStringAsync();
contentTask.Wait();
var googleContent = contentTask.Result;
GD.Print(googleContent);
}

public async Task Hangs()
{
var google = await _httpClient.GetAsync("https://www.google.com");
var googleContent = await google.Content.ReadAsStringAsync();
GD.Print(googleContent);
}
}
```
![Animation](https://github.com/godotengine/godot/assets/5092066/9c6b6700-b652-4dd9-8288-623a497629db)

### Minimal reproduction project (MRP)

[demo.zip](https://github.com/godotengine/godot/files/15218299/demo.zip)

Contributor guide

Open the contributing guide

Research direction

Start with the attached demo.zip in a new C# project and run the TestScript entry point with the debugger enabled. Compare _Ready(), Works(), and Hangs() to reproduce the difference between blocking waits and await; done means Hangs() completes and prints the fetched content instead of remaining stuck.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
developer-experience, game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.