1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Linq;
9 using System.Collections.Generic;
10 using System.Runtime.ExceptionServices;
11 
12 namespace Antmicro.Renode.Utilities.Binding
13 {
14     public class ExceptionKeeper
15     {
AddException(Exception e)16         public void AddException(Exception e)
17         {
18             // ExceptionKeeper holds the raised exception and throws it at a later time
19             // so we use ExceptionDispatchInfo to preserve the original stacktrace.
20             // Otherwise exception's stacktrace changes when it's rethrown.
21             var dispatchInfo = ExceptionDispatchInfo.Capture(e);
22             exceptions.Add(dispatchInfo);
23         }
24 
ThrowExceptions()25         public void ThrowExceptions()
26         {
27             if(!exceptions.Any())
28             {
29                 return;
30             }
31 
32             try
33             {
34                 if(exceptions.Count == 1)
35                 {
36                     exceptions[0].Throw();
37                 }
38 
39                 throw new Exception
40                 (
41                     "Multiple errors occured within tlib managed->native->managed boundary since the last ThrowExceptions call.",
42                     new AggregateException(exceptions.Select(x => x.SourceException))
43                 );
44             }
45             finally
46             {
47                 exceptions.Clear();
48             }
49         }
50 
PrintExceptions()51         public void PrintExceptions()
52         {
53             foreach(var exception in exceptions)
54             {
55                 Console.WriteLine(exception.SourceException);
56             }
57         }
58 
59         private readonly List<ExceptionDispatchInfo> exceptions = new List<ExceptionDispatchInfo>();
60     }
61 }
62