Search Unity

Bug Unobserved "Collection was modified" exception from HttpClient dispose

Discussion in 'Scripting' started by ahatala_meta, Oct 22, 2021.

  1. ahatala_meta

    ahatala_meta

    Joined:
    Sep 22, 2021
    Posts:
    1
    We are seeing unobserved exceptions being thrown from use of System.Net.Http.HttpClient. The exception happens upon dispose of HttpClient when a request has not been completed successfully (for example due to a NameResolutionFailure). The callstack looks like this:

    Code (CSharp):
    1. InvalidOperationException: Collection was modified; enumeration operation may not execute.
    2.   at System.Collections.Generic.Dictionary`2+Enumerator[TKey,TValue].MoveNext () [0x00000] in <00000000000000000000000000000000>:0
    3.   at System.Net.ServicePointScheduler.RunSchedulerIteration () [0x00000] in <00000000000000000000000000000000>:0
    4.   at System.Net.ServicePointScheduler+<StartScheduler>d__32.MoveNext () [0x00000] in <00000000000000000000000000000000>:0
    5.   at System.Threading.ContextCallback.Invoke (System.Object state) [0x00000] in <00000000000000000000000000000000>:0
    6.   at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <00000000000000000000000000000000>:0
    7.   at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run () [0x00000] in <00000000000000000000000000000000>:0
    8.   at System.Threading.ThreadStart.Invoke () [0x00000] in <00000000000000000000000000000000>:0
    While it seems that this exception doesn't have direct user-visible impact it creates clutter in our error reporting systems and since it happens within the System.Net implementation we haven't been able to figure out a decent way of gracefully filtering out this exception from reporting tools.

    The root cause appears to have been reported to mono and fixed a while ago in https://github.com/mono/mono/pull/7359, but apparently the fix has not been backported to the Unity fork.

    Find below a minimal MonoBehaviour script that should trigger the issue (tested with Unity version 2020.3.17f1). Dropping this into a GameObject in an otherwise empty scene and running a standalone player build should generate the InvalidOperationException with call stack shown above.

    Code (CSharp):
    1. using System.Net.Http;
    2. using System.Threading.Tasks;
    3. using UnityEngine;
    4.  
    5. public class Repro : MonoBehaviour
    6. {
    7.     void Awake()
    8.     {
    9.         Task.Run(Bug);
    10.     }
    11.  
    12.     async Task Bug()
    13.     {
    14.         using (var client = new HttpClient()) {
    15.             await client.GetAsync("http://nonexistent");
    16.         }
    17.     }
    18. }
     
    Last edited: Oct 22, 2021