runtime: Quic exception in the guts of making an http request

Description

I have a game server that is using dotnet core 3.1, and I have recently begun building it for .net 7 to get away on a newer supported .net version. We are building this game server in self contained mode with a targeted runtime to make it completely self sufficient.

This server application is a console app, and one of the first things it does as part of starting up the server into the configured map is query mod.io for a template file to see if it needs to download the template file or whether the file hash matches the local file.

This fairly basic http query is failing seemingly within the code that is supposed to be checking whether QuicConnection IsSupported. Here is a callstack

BuildVerseServer.Server - DownloadTemplateFromModIO Exception
System.AggregateException: One or more errors occurred. (The type initializer for 'System.Net.Quic.MsQuicApi' threw an exception.)
 ---> System.TypeInitializationException: The type initializer for 'System.Net.Quic.MsQuicApi' threw an exception.
 ---> System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception.
   at System.Net.Quic.MsQuicApi.TryOpenMsQuic(QUIC_API_TABLE*& apiTable, Int32& openStatus)
   at System.Net.Quic.MsQuicApi..cctor()
   --- End of inner exception stack trace ---
   at System.Net.Quic.QuicConnection.get_IsSupported()
   at System.Net.Http.HttpConnectionPool..ctor(HttpConnectionPoolManager poolManager, HttpConnectionKind kind, String host, Int32 port, String sslHostName, Uri proxyUri)
   at System.Net.Http.HttpConnectionPoolManager.SendAsyncCore(HttpRequestMessage request, Uri proxyUri, Boolean async, Boolean doRequestAuth, Boolean isProxyConnect, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPoolManager.SendAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpMessageHandlerStage.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at Modio.Connection.Send[T](Request request) in C:\JenkinsHome\workspace\CreativerseStandalone\Server\Modio\Http\Connection.cs:line 41
   at Modio.SearchClient`1.ToPagedEnumerable()+MoveNext() in C:\JenkinsHome\workspace\CreativerseStandalone\Server\Modio\Clients\SearchClient.cs:line 90
   at Modio.SearchClient`1.ToPagedEnumerable()+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
   at Modio.SearchClient`1.ToList() in C:\JenkinsHome\workspace\CreativerseStandalone\Server\Modio\Clients\SearchClient.cs:line 54
   at Modio.SearchClient`1.ToList() in C:\JenkinsHome\workspace\CreativerseStandalone\Server\Modio\Clients\SearchClient.cs:line 54

After some reading in several issues here on github. It seems that some of this Quic stuff or higher http versions that utilize it should be opt-in, and we aren’t opting in, so I’m not sure why it is attempting to use/initialize Quic. In any case I thought it seemed suspect that the bowels of a completely optional component Quic could fail out of the entire attempt, rather than be caught and treated as non supported.

Reproduction Steps

Reproduction is impractical to communicate, because this occurs in a highly specific circumstance of running the dedicated server app via steam on the steam deck handheld gaming device. What’s more, is that this only occurs when running the server in this way. If we run the native linux version of the server via terminal on the steam deck, this issue does not occur. My guess is the presence of Quic support is being effected by the emulation layer that apps run on when launched via steam on the steam deck device.

Expected behavior

I guess I would expect Quic support to report false and the app to continue without it, not fail with an exception all the way back up to user code.

Actual behavior

Within the call context of System.Net.Quic.QuicConnection.get_IsSupported(), an uncaught exception causes the entire callstack to unwind back to user code and the http request to fail completely.

Regression?

We are brand new at experimenting with running our game/server on the steam deck device. These issues are unique to running the application on top of the proton emulation layer, so while one may point to that as being the emulation layers problem, the nature of the failure to me suggests there is the possibility of a supposedly optional component(Quic) IsSupported function failing spectacularly and breaking the whole attempt.

Known Workarounds

None

Configuration

.net 7 steam OS

Other information

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (13 by maintainers)

Most upvoted comments

You can do LD_DEBUG=libs ./myApp That would show library loading and any bits not visible by the package manager.