private static bool GetNewRulesAndPrepareContext(out FaultRule[] newRules, string currentFunction) { try { newRules = FaultRuleLoader.Load(); } catch (FaultInjectionException e) { throw e; } catch (Exception e) { throw new FaultInjectionException(FaultDispatcherMessages.LoadFaultRuleError, e); } if (newRules == null || newRules.Length == 0) { return(false); } lock (initialized) { if (contexts == null) { int length = newRules.Length; contexts = new RuntimeContext[length]; for (int i = 0; i < length; ++i) { contexts[i] = new RuntimeContext(); } } } return(true); }
/// <summary> /// Checks that /// </summary> public void AssertFaultInjectionEnabled() { StringBuilder errors = new StringBuilder(); // Verify registry if (!ComRegistrar.IsRegistered()) { errors.AppendLine(ApiErrorMessages.EngineNotRegistered); } // Verify profiler environment variables. // Is "COMPLUS_ProfAPI_ProfilerCompatibilitySetting=EnableV2Profiler" still needed? if (Environment.GetEnvironmentVariable(EnvironmentVariable.EnableProfiling) != "1") { errors.AppendLine(ApiErrorMessages.ProfilerNotEnabled); } string profiler = Environment.GetEnvironmentVariable(EnvironmentVariable.Profiler); if (profiler != EngineInfo.Engine_CLSID) { errors.AppendLine(string.Format(ApiErrorMessages.ProfilerNotSpecified, profiler)); } if (Environment.GetEnvironmentVariable(EnvironmentVariable.ProfilerCompatibilityForCLR4) != EnvironmentVariable.EnableV2Profiler) { errors.AppendLine(ApiErrorMessages.ProfilerV2CompatibilityNotSpecified); } // Verify log directory string logDirectory = Environment.GetEnvironmentVariable(EnvironmentVariable.LogDirectory); if (String.IsNullOrEmpty(logDirectory) || logDirectory.Trim().Length == 0) { errors.AppendLine(ApiErrorMessages.LogDirectoryNotSet); } else if (!Directory.Exists(logDirectory)) { errors.AppendLine(string.Format(ApiErrorMessages.LogDirectoryAccessDenied, logDirectory)); } // Verify that fault rules can be loaded FaultRule[] rules = FaultRuleLoader.Load(); if (rules == null) { errors.AppendLine(ApiErrorMessages.NoFaultRulesLoaded); } // Verify that the method filter file exists string methodFilterFileName = Environment.GetEnvironmentVariable(EnvironmentVariable.MethodFilter); if (string.IsNullOrEmpty(methodFilterFileName)) { errors.AppendLine(ApiErrorMessages.MethodFilterFileNotSet); } else { StreamReader methodFilterFile = null; try { // Verify that the method filter file contains an entry for every method that has a fault rule methodFilterFile = File.OpenText(methodFilterFileName); List <string> methodFilterContents = new List <string>(); while (!methodFilterFile.EndOfStream) { methodFilterContents.Add(methodFilterFile.ReadLine().Trim()); } bool allEntriesFound = true; foreach (FaultRule r in rules) { string comSignature = Signature.ConvertSignature(r.MethodSignature, SignatureStyle.Com); if (!methodFilterContents.Any(s => s == comSignature)) { allEntriesFound = false; errors.AppendLine( string.Format(ApiErrorMessages.MethodFilterFileHasMissingEntry, Environment.GetEnvironmentVariable(EnvironmentVariable.MethodFilter), r.MethodSignature, comSignature)); } } if (!allEntriesFound) { errors.AppendLine(string.Format(ApiErrorMessages.MethodFilterFileContentsDump, methodFilterFileName)); foreach (string s in methodFilterContents) { errors.AppendLine(s); } } } catch (IOException e) { if (methodFilterFile != null) { methodFilterFile.Dispose(); } errors.AppendLine(string.Format(ApiErrorMessages.MethodFilterFileAccessDenied, methodFilterFileName)); errors.Append("\t"); errors.AppendLine(e.Message); } } // Verify FaultDispatcher.Trap() method exists and can be loaded by the current runtime FaultDispatcherDelegate t = FaultDispatcher.Trap; // Verify FaultDispatcher assembly has the public key token that the engine expects string faultDispatcherAssemblyName = typeof(FaultDispatcher).Assembly.FullName; if (!faultDispatcherAssemblyName.Contains(EngineInfo.FaultDispatcherAssemblyPublicKeyToken)) { errors.AppendLine(string.Format(ApiErrorMessages.FaultDispatcherCannotBeLoaded, faultDispatcherAssemblyName)); } // Now throw the errors if they exist if (errors.Length != 0) { throw new FaultInjectionException(errors.ToString()); } }
/// <summary> /// Injected into the prologue of the target method. /// </summary> /// <param name="exceptionValue">Exception thrown by fault</param> /// <param name="returnValue">Value to return from fault</param> /// <returns></returns> /// <remarks> /// Trap creates a RuntimeContext for the current call and evaluates /// the fault condition's Trigger method. If it evaluates to true /// the fault's Retrieve method is called. /// </remarks> public static bool Trap(out Exception exceptionValue, out Object returnValue) { exceptionValue = null; returnValue = null; FaultRule[] newRules; try { newRules = FaultRuleLoader.Load(); } catch (Exception e) { throw new FaultInjectionException(FaultDispatcherMessages.LoadFaultRuleError, e); } if (newRules == null || newRules.Length == 0) { return(false); } StackTrace stackTrace = new StackTrace(1); CallStack callStack = new CallStack(stackTrace); //stackFrame does not include Trap() StackFrame stackFrame = stackTrace.GetFrame(0); String currentFunction = callStack[0]; RuntimeContext currentContext = null; FaultRule rule = null; try { //Get Fault Rule and Update current RuntimeContext int len = newRules.Length; for (int i = 0; i < len; ++i) { if (newRules[i].FormalSignature != null && currentFunction.Equals(newRules[i].FormalSignature) == true) { rule = newRules[i]; currentContext = new RuntimeContext(); currentContext.CalledTimes = rule.IncrementAndReturnNumTimesCalled(); currentContext.CallStack = callStack; currentContext.CallStackTrace = stackTrace; break; } } //Using ICondition and IFault if (rule == null) { return(false); } bool triggered = false; try { triggered = rule.Condition.Trigger(currentContext); if (triggered == true) { rule.Fault.Retrieve(currentContext, out (exceptionValue), out returnValue); } } catch (System.Exception e) { throw new FaultInjectionException(FaultDispatcherMessages.NoExceptionAllowedInTriggerAndRetrieve, e); } if (!triggered) { return(false); } } catch (System.Exception e) { throw new FaultInjectionException(FaultDispatcherMessages.UnknownExceptionInTrap, e); } // check return-value's type if not to throw exception if (null == exceptionValue) { if (stackFrame.GetMethod() is ConstructorInfo) { return(true); } Type returnTypeOfTrappedMethod = ((MethodInfo)stackFrame.GetMethod()).ReturnType; return(CheckReturnType(returnTypeOfTrappedMethod, returnValue, currentFunction)); } return(true); }