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