示例#1
0
        /// <summary>
        /// Log a race condition.
        /// </summary>
        /// <param name="trap">Trap details.</param>
        /// <param name="trappedPoint">InterceptionPoint that got trapped.</param>
        /// <returns><see langword="true" /> if XXXX, <see langword="false" /> otherwise.</returns>
        public static bool WriteBug(Trap trap, InterceptionPoint trappedPoint)
        {
            if (bugLogger == null)
            {
                return(false);
            }

            string bug = trap.InterceptionPoint.Method + ";" + trap.InterceptionPoint.API + ";" + trap.InterceptionPoint.ILOffset + ";" + trap.InterceptionPoint.StackTrace + "\n"
                         + trappedPoint.Method + ";" + trappedPoint.API + ";" + trappedPoint.ILOffset + ";" + trappedPoint.StackTrace;

            if (!KnownBugs.Contains(bug))
            {
                KnownBugs.Add(bug);

                List <string> lines = new List <string>();
                lines.Add("---Race Condition---");
                lines.Add("---Trap---");
                lines.AddRange(LogHelper.GetInterceptionPointLogLines(trap.InterceptionPoint, trap.ObjectId, true));
                lines.Add(string.Format("Delay: {0}", trap.Delay));
                lines.Add("---Trapped---");
                lines.AddRange(LogHelper.GetInterceptionPointLogLines(trappedPoint, trap.ObjectId, true));
                bugLogger.Log(lines);

                return(true);
            }

            return(false);
        }
示例#2
0
        /// <summary>
        /// Callback invoked before a method is called.
        /// </summary>
        /// <param name="instance">Instance object on which the method is called. Null if the method is static.</param>
        /// <param name="caller">Parent method that calls the method.</param>
        /// <param name="ilOffset">ILOffset where the method is invoked.</param>
        /// <param name="callee">Name of the called method.</param>
        /// <returns>A context given to AfterMethodCall callback.</returns>
        public static MethodCallbackContext BeforeMethodCall(object instance, string caller, int ilOffset, string callee)
        {
            // string uniqueFieldName = GetUniqueFieldId(parentObject, fieldName);
            // Guid objId = ObjectId.GetRefId(instance);
            InterceptionPoint interceptionPoint = new InterceptionPoint()
            {
                Method    = caller,
                API       = "Read " + MethodSignatureWithoutReturnType(callee),
                ILOffset  = ilOffset,
                ThreadId  = Thread.CurrentThread.ManagedThreadId,
                ObjID     = ObjectId.GetRefId(instance).ToString(),
                GroupName = "No-Group",
                IsWrite   = false,
            };
            var    objId   = ObjectId.GetRefId(instance);
            string fieldId = "null";

            if (FieldNameDict.ContainsKey(objId))
            {
                fieldId = FieldNameDict[objId];
            }

            Configuration.TrapController.InterceptionPointStart(interceptionPoint, instance);
            return(new MethodCallbackContext()
            {
                Instance = instance, FieldId = fieldId, Caller = caller, ILOffset = ilOffset, Callee = callee
            });
        }
示例#3
0
        /// <summary>
        /// Updates the tp history.
        /// </summary>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        private void UpdateTPHistory(InterceptionPoint interceptionPoint)
        {
            // update the last operation for each thread
            lock (this.perThreadLastTP)
            {
                this.perThreadLastTP[interceptionPoint.ThreadId] = interceptionPoint;
            }

            // this block monitor the history of InterceptionPoints to infer the concurrent threads
            lock (this.globalTPHistory)
            {
                int thdid = interceptionPoint.ThreadId;
                this.globalTPHistory.Enqueue(interceptionPoint);
                if (this.perThreadTPCount.ContainsKey(thdid))
                {
                    this.perThreadTPCount[thdid]++;
                }
                else
                {
                    this.perThreadTPCount[thdid] = 1;
                }

                if (this.globalTPHistory.Count > this.HistoryWindowSize)
                {
                    InterceptionPoint tp = this.globalTPHistory.Dequeue();
                    this.perThreadTPCount[tp.ThreadId]--;
                    if (this.perThreadTPCount[tp.ThreadId] == 0)
                    {
                        this.perThreadTPCount.Remove(tp.ThreadId);
                    }
                }

                interceptionPoint.ActiveThdNum = this.perThreadTPCount.Keys.Count;
            }
        }
示例#4
0
        /// <summary>
        /// Locks the related op.
        /// </summary>
        /// <param name="tp">The tp.</param>
        /// <returns><see langword="true" /> if XXXX, <see langword="false" /> otherwise.</returns>
        private bool LockRelatedOP(InterceptionPoint tp)
        {
            if (tp.API.StartsWith("System.Threading.Monitor.Enter") || tp.API.StartsWith("System.Threading.Monitor.Exit"))
            {
                return(true);
            }

            return(false);
        }
示例#5
0
        /// <summary>
        /// Logs the bug for next run.
        /// </summary>
        /// <param name="tp1">The TP1.</param>
        /// <param name="tp2">The TP2.</param>
        private void LogBugForNextRun(InterceptionPoint tp1, InterceptionPoint tp2)
        {
            string bugSignature = this.GetPairID(tp1.Location, tp2.Location);

            if (!this.knownBugs.ContainsKey(bugSignature) && !this.blacklist.Contains(bugSignature))
            {
                this.knownBugs[bugSignature] = 1;
                this.lastRunBugLogger.Log(bugSignature);
            }
        }
示例#6
0
        /// <summary>
        /// Get InterceptionPoint Log lines.
        /// </summary>
        /// <param name="interceptionPoint">InterceptionPoint information.</param>
        /// <returns>Log lines for InterceptionPoint.</returns>
        public static List <string> GetInterceptionPointLogLines(InterceptionPoint interceptionPoint)
        {
            List <string> lines = new List <string>();

            lines.Add(string.Format("Id: {0}", interceptionPoint.GLobalHitCount));
            lines.Add(string.Format("ThreadId: {0}", interceptionPoint.ThreadId));
            lines.Add(string.Format("Timestamp: {0}", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fff", CultureInfo.InvariantCulture)));
            lines.Add(string.Format("API: {0}", interceptionPoint.API));
            lines.Add(string.Format("Method: {0}", interceptionPoint.Method));
            lines.Add(string.Format("ILOffset: {0}", interceptionPoint.ILOffset));
            return(lines);
        }
示例#7
0
        /// <summary>
        /// Method called right before an intercepted api.
        /// </summary>
        /// <param name="instance">Object instance of the called API.</param>
        /// <param name="method">Name of the method calling the api.</param>
        /// <param name="api">intercepeted API name.</param>
        /// <param name="ilOffset">ILOffset of the API call.</param>
        public static void OnStart(object instance, string method, string api, int ilOffset)
        {
            InterceptionPoint interceptionPoint = new InterceptionPoint()
            {
                Method   = method,
                API      = MethodSignatureWithoutReturnType(api),
                ILOffset = ilOffset,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
            };

            Configuration.TrapController.InterceptionPointStart(interceptionPoint, instance);
        }
示例#8
0
        /// <summary>
        /// Get InterceptionPoint Log lines.
        /// </summary>
        /// <param name="interceptionPoint">InterceptionPoint information.</param>
        /// <param name="objId">Id of the instance object.</param>
        /// <param name="includeStackTrace">A value indicating whether stack trace should be included as a log line.</param>
        /// <returns>Log lines for InterceptionPoint.</returns>
        public static List <string> GetInterceptionPointLogLines(InterceptionPoint interceptionPoint, int objId, bool includeStackTrace)
        {
            List <string> lines = new List <string>();

            lines.AddRange(GetInterceptionPointLogLines(interceptionPoint));
            lines.Add(string.Format("ObjectId: {0}", objId));
            if (includeStackTrace)
            {
                lines.Add(string.Format("StackTrace: {0}", interceptionPoint.StackTrace));
            }

            return(lines);
        }
示例#9
0
        /// <summary>
        /// Finds a matching <see cref="TrapPlan" />.
        /// </summary>
        /// <param name="interceptionPoint">CUrrent InterceptionPoint.</param>
        /// <param name="globalHitcountWindow">Global hitcount window.</param>
        /// <param name="localHitcountWindow">Local hitcount window.</param>
        /// <returns>A matching <see cref="TrapPlan" />.</returns>
        public TrapPlan FindMatchingPlan(InterceptionPoint interceptionPoint, int globalHitcountWindow = 20, int localHitcountWindow = 5)
        {
            if (interceptionPoint == null || interceptionPoint.API == null)
            {
                return(null);
            }

            var planId = TrapPlan.GetID(interceptionPoint.API, interceptionPoint.Method, interceptionPoint.ILOffset);

            if (this.nonwildCardPlans.ContainsKey(planId))
            {
                var  plan    = this.nonwildCardPlans[planId];
                bool isMatch = (plan.ThreadId == null || string.Equals(plan.ThreadId, interceptionPoint.ThreadId)) &&
                               (plan.HitCounts == null || plan.HitCounts.Count(x => x.IsMatch(interceptionPoint.LocalHitcount, localHitcountWindow, interceptionPoint.GLobalHitCount, globalHitcountWindow)) > 0);

                return(isMatch ? plan : null);
            }

            foreach (var plan in this.wildCardPlans)
            {
                if (!SignatureMatchUtils.IsWildcardMatch(interceptionPoint.API, plan.API))
                {
                    continue;
                }

                if (plan.Method != null && !SignatureMatchUtils.IsWildcardMatch(interceptionPoint.Method, plan.Method))
                {
                    continue;
                }

                if (plan.ILOffset >= 0 && plan.ILOffset != interceptionPoint.ILOffset)
                {
                    continue;
                }

                if (plan.ThreadId != null && !string.Equals(plan.ThreadId, interceptionPoint.ThreadId))
                {
                    continue;
                }

                if (plan.HitCounts != null && plan.HitCounts.Count(x => x.IsMatch(interceptionPoint.LocalHitcount, localHitcountWindow, interceptionPoint.GLobalHitCount, globalHitcountWindow)) > 0)
                {
                    continue;
                }

                return(plan);
            }

            return(null);
        }
示例#10
0
        /// <summary>
        /// Updates the tp hit counts.
        /// </summary>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        private void UpdateTPHitCounts(InterceptionPoint interceptionPoint)
        {
            string location = interceptionPoint.API + "|" + interceptionPoint.Method + "|" + interceptionPoint.ILOffset.ToString();

            interceptionPoint.Location = location;
            lock (this.perTPHitCount)
            {
                if (!this.perTPHitCount.ContainsKey(location))
                {
                    this.perTPHitCount[location] = 0;
                }

                interceptionPoint.LocalHitcount = this.perTPHitCount[location];
                this.perTPHitCount[location]    = interceptionPoint.LocalHitcount + 1;
            }
        }
示例#11
0
        /// <summary>
        /// Finishes the trap.
        /// </summary>
        /// <param name="trapObjects">The trap objects.</param>
        /// <param name="trap">The trap.</param>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        private void FinishTrap(Dictionary <string, HashSet <Trap> > trapObjects, Trap trap, InterceptionPoint interceptionPoint)
        {
            // execute the sleep
            if (trap != null)
            {
                try
                {
                }
                finally
                {
                    Thread.BeginCriticalRegion();
                    trap.Semaphore.WaitOne(trap.Delay);
                    ControllerHelper.Debug("Sleep : " + interceptionPoint.Tostring());
                    lock (trapObjects)
                    {
                        trapObjects.Remove(trap.ObjectId);
                    }

                    Thread.EndCriticalRegion();
                }

                interceptionPoint.DelayCredit = this.InferSize;

                // figure out the which thread is blocked by this trap.
                {
                    lock (this.perThreadLastTP)
                    {
                        foreach (var x in this.perThreadLastTP.Keys)
                        {
                            InterceptionPoint tp2 = this.perThreadLastTP[x];
                            if (interceptionPoint.Timestamp.AddMilliseconds(this.DelayPerDangerousInterceptionPoint * this.InferLimit) > tp2.Timestamp)
                            {
                                this.perThreadBlockedTP[x] = interceptionPoint;
                            }
                        }
                    }
                }

                interceptionPoint.Trapped = true;

                this.isTrapActive = false;
            }
        }
示例#12
0
        /// <summary>
        /// Callback invoked before a field is read.
        /// </summary>
        /// <param name="parentObject">Object owning the field.</param>
        /// <param name="fieldName">Field name.</param>
        /// <param name="fieldValue">Field value.</param>
        /// <param name="caller">Method that writes the field.</param>
        /// <param name="ilOffset">ILOffset where the write happens.</param>
        public static void BeforeFieldRead(object parentObject, string fieldName, object fieldValue, string caller, int ilOffset)
        {
            string            uniqueFieldName   = GetUniqueFieldId(parentObject, fieldName);
            Guid              objId             = ObjectId.GetRefId(fieldValue);
            InterceptionPoint interceptionPoint = new InterceptionPoint()
            {
                Method    = caller,
                API       = "Read " + MethodSignatureWithoutReturnType(fieldName),
                ILOffset  = ilOffset,
                ThreadId  = Thread.CurrentThread.ManagedThreadId,
                ObjID     = uniqueFieldName,
                GroupName = fieldName,
                IsWrite   = false,
            };

            Configuration.TrapController.InterceptionPointStart(interceptionPoint, parentObject);

            //Logger.Log($"BeforeFieldRead\t{uniqueFieldName}\t{objId}\t{caller}\t{ilOffset}");
        }
示例#13
0
        /// <summary>
        /// Get thread safety group details of the InterceptionPoint.
        /// </summary>
        /// <param name="interceptionPoint">InterceptionPoint.</param>
        /// <returns>Thread safety InterceptionPoint.</returns>
        private ThreadSafetyInterceptionPoint GetThreadSafetyInterceptionPoint(InterceptionPoint interceptionPoint)
        {
            if (this.threadSafetyInterceptionPointCache.ContainsKey(interceptionPoint.API))
            {
                return(this.threadSafetyInterceptionPointCache[interceptionPoint.API]);
            }

            foreach (ThreadSafetyGroup threadSafetyGroup in this.configuration.ThreadSafetyGroups)
            {
                foreach (string writeAPI in threadSafetyGroup.WriteAPIs)
                {
                    if (SignatureMatchUtils.IsWildcardMatch(interceptionPoint.API, writeAPI))
                    {
                        var tsInterceptionPoint = new ThreadSafetyInterceptionPoint()
                        {
                            ThreadSafetyGroup = threadSafetyGroup,
                            IsWriteAPI        = true,
                        };
                        this.threadSafetyInterceptionPointCache[interceptionPoint.API] = tsInterceptionPoint;
                        return(tsInterceptionPoint);
                    }
                }

                foreach (string readAPI in threadSafetyGroup.ReadAPIs)
                {
                    if (SignatureMatchUtils.IsWildcardMatch(interceptionPoint.API, readAPI))
                    {
                        var tsInterceptionPoint = new ThreadSafetyInterceptionPoint()
                        {
                            ThreadSafetyGroup = threadSafetyGroup,
                            IsWriteAPI        = false,
                        };
                        this.threadSafetyInterceptionPointCache[interceptionPoint.API] = tsInterceptionPoint;
                        return(tsInterceptionPoint);
                    }
                }
            }

            return(null);
        }
示例#14
0
        /// <summary>
        /// Shoulds the return without trap.
        /// </summary>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        /// <param name="instance">The instance.</param>
        /// <returns><see langword="true" /> if XXXX, <see langword="false" /> otherwise.</returns>
        private bool ShouldReturnWithoutTrap(InterceptionPoint interceptionPoint, object instance)
        {
            // this.Updatelockinformation(InterceptionPoint);
            if (this.LockRelatedOP(interceptionPoint))
            {
                return(true);
            }

            // Locate the APIs bypass the lock operation
            ThreadSafetyInterceptionPoint threadSafetyInterceptionPoint = this.GetThreadSafetyInterceptionPoint(interceptionPoint);

            if (threadSafetyInterceptionPoint == null)
            {
                return(true);
            }

            if (!threadSafetyInterceptionPoint.ThreadSafetyGroup.IsStatic && instance == null)
            {
                return(true);
            }

            return(false);
        }
示例#15
0
        /// <summary>
        /// Removes the dependent InterceptionPoints.
        /// </summary>
        /// <param name="tp">The tp.</param>
        private void RemoveDependentInterceptionPoints(InterceptionPoint tp)
        {
            lock (this.perThreadLastTP)
            {
                if (this.perThreadBlockedTP.ContainsKey(tp.ThreadId))
                {
                    // find the InterceptionPoint that blocked this thread if exists.
                    InterceptionPoint tp2 = this.perThreadBlockedTP[tp.ThreadId];

                    // delaycredit is k means a InterceptionPoint block the next-k operation in other thread
                    if (tp2.DelayCredit > 0)
                    {
                        this.RemoveDangerItem(tp.Location, tp2.Location);

                        // DebugLog.Log("HB Order " + tp.Tostring() + " " + tp2.Tostring());
                        tp2.DelayCredit--;
                    }
                    else
                    {
                        this.perThreadBlockedTP.Remove(tp.ThreadId);
                    }
                }
            }
        }
示例#16
0
        /// <summary>
        /// Finishes the trap.
        /// </summary>
        /// <param name="trapObjects">The trap objects.</param>
        /// <param name="trap">The trap.</param>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        private void FinishTrap(Dictionary <Guid, HashSet <Trap> > trapObjects, Trap trap, InterceptionPoint interceptionPoint)
        {
            // execute the sleep
            if (trap != null)
            {
                // DebugLog.Log("Start Sleeping  for tp " + InterceptionPoint.Tostring());
                trap.Semaphore.WaitOne(trap.Delay);
                interceptionPoint.DelayCredit = this.InferSize;

                // figure out the which thread is blocked by this trap.
                {
                    lock (this.perThreadLastTP)
                    {
                        foreach (var x in this.perThreadLastTP.Keys)
                        {
                            InterceptionPoint tp2 = this.perThreadLastTP[x];
                            if (interceptionPoint.Timestamp.AddMilliseconds(this.DelayPerDangerousInterceptionPoint * this.InferLimit) > tp2.Timestamp)
                            {
                                this.perThreadBlockedTP[x] = interceptionPoint;

                                // DebugLog.Log(x + " is blocked by " + InterceptionPoint.Tostring());
                            }
                        }
                    }
                }

                interceptionPoint.Trapped = true;

                lock (trapObjects)
                {
                    trapObjects.Remove(trap.ObjectId);
                }

                this.isTrapActive = false;
            }
        }
示例#17
0
        /// <summary>
        /// Get thread safety group details of the InterceptionPoint.
        /// </summary>
        /// <param name="threadSafetyGroups">The thread safety groups.</param>
        /// <param name="interceptionPoint">InterceptionPoint.</param>
        /// <returns>Thread safety InterceptionPoint.</returns>
        public static ThreadSafetyInterceptionPoint GetThreadSafetyInterceptionPoint(List <ThreadSafetyGroup> threadSafetyGroups, InterceptionPoint interceptionPoint)
        {
            if (threadSafetyGroups == null)
            {
                return(null);
            }

            foreach (ThreadSafetyGroup threadSafetyGroup in threadSafetyGroups)
            {
                foreach (string writeAPI in threadSafetyGroup.WriteAPIs)
                {
                    if (SignatureMatchUtils.IsWildcardMatch(interceptionPoint.API, writeAPI))
                    {
                        return(new ThreadSafetyInterceptionPoint()
                        {
                            ThreadSafetyGroup = threadSafetyGroup,
                            IsWriteAPI = true,
                        });
                    }
                }

                foreach (string readAPI in threadSafetyGroup.ReadAPIs)
                {
                    if (SignatureMatchUtils.IsWildcardMatch(interceptionPoint.API, readAPI))
                    {
                        return(new ThreadSafetyInterceptionPoint()
                        {
                            ThreadSafetyGroup = threadSafetyGroup,
                            IsWriteAPI = false,
                        });
                    }
                }
            }

            return(null);
        }
示例#18
0
        /// <summary>
        /// Finds the racing tp.
        /// </summary>
        /// <param name="tp">The tp.</param>
        /// <returns>System.String.</returns>
        private string FindRacingTP(InterceptionPoint tp)
        {
            List <InterceptionPoint> list = new List <InterceptionPoint>();

            // this block goes through the last-k tps that access the same object to find the dangerous list.co
            lock (this.lastInterceptionPointForOBJ)
            {
                if (this.lastInterceptionPointForOBJ.ContainsKey(tp.ObjID))
                {
                    Queue <InterceptionPoint> q = this.lastInterceptionPointForOBJ[tp.ObjID];
                    foreach (var tp2 in q)
                    {
                        // from different thread and at least one is write
                        if ((tp2.ThreadId != tp.ThreadId) && (tp.IsWrite || tp2.IsWrite))
                        {
                            // close enough from timing prespective
                            if (tp2.Timestamp.AddMilliseconds(this.planDistance) > tp.Timestamp)
                            {
                                // the next condition is always true as we ignore the lock. Every LockState is false.
                                if ((tp2.LockState == false) || (tp.LockState == false))
                                {
                                    if ((tp2.ActiveThdNum > 1) || (tp.ActiveThdNum > 1))
                                    {
                                        list.Add(tp2);
                                    }
                                }
                            }
                        }
                    }

                    // update the last access for this object
                    q.Enqueue(tp);
                    if (q.Count > this.LastTPWindow)
                    {
                        q.Dequeue();
                    }
                }
                else
                {
                    this.lastInterceptionPointForOBJ[tp.ObjID] = new Queue <InterceptionPoint>();
                    this.lastInterceptionPointForOBJ[tp.ObjID].Enqueue(tp);
                }
            }

            // update the dangerous pair list
            string           s    = string.Empty;
            HashSet <string> temp = new HashSet <string>();

            foreach (InterceptionPoint tp2 in list)
            {
                string st  = tp.Tostring() + " ! " + tp2.Tostring();
                string st2 = tp2.Tostring() + " ! " + tp.Tostring();
                Tuple <string, string> tuple = new Tuple <string, string>(tp.Tostring(), tp2.Tostring());
                string shortst = this.GetPairID(st, st2);

                string pairname = this.GetPairID(tp.Location, tp2.Location);
                if (this.blacklist.Contains(pairname))
                {
                    // the blacklist contains the bugs found in previous ROUNDS. DebugLog.Log("Skip blacked pair " + shortst);
                    continue;
                }

                bool flag = false;
                lock (this.dangerousTPPairs)
                {
                    if (this.hitTime.ContainsKey(tp.Location) && this.hitTime.ContainsKey(tp2.Location) && (this.hitTime[tp.Location] + this.hitTime[tp2.Location] >= 10) && this.dangerousTPPairs.Contains(shortst))
                    {
                        continue;
                    }

                    // the hittime is how many time this dangerous pair has caused trap. It is used for decay.
                    this.hitTime[tp.Location]  = 0;
                    this.hitTime[tp2.Location] = 0;
                    this.dangerousTPPairs.Add(shortst);
                    flag = true;
                }

                if (flag)
                {
                    // DebugLog.Log("AddDangerList : " + st);
                    this.LogPlanForNextRun(st);
                }
            }

            return(s);
        }
示例#19
0
        /// <summary>
        /// Checks for bugs and start trap.
        /// </summary>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        /// <param name="threadSafetyInterceptionPoint">The thread safety InterceptionPoint.</param>
        /// <param name="trapObjects">The trap objects.</param>
        /// <param name="trapPlan">The trap plan.</param>
        /// <param name="instance">The instance.</param>
        /// <param name="bugFound">If set to <see langword="true" /> then a bug has been found.</param>
        /// <returns>Trap.</returns>
        private Trap CheckForBugsAndStartTrap(InterceptionPoint interceptionPoint, ThreadSafetyInterceptionPoint threadSafetyInterceptionPoint, Dictionary <Guid, HashSet <Trap> > trapObjects, TrapPlan trapPlan, object instance, out bool bugFound)
        {
            int       danger           = -1;
            Semaphore semaphore        = null;
            double    prob             = 1.0;
            int       sleepDuration    = 0;
            Guid      objectId         = interceptionPoint.ObjID;
            bool      continueAfterBug = false;

            bugFound = false;
            Trap newTrap = null;

            lock (trapObjects)
            {
                // Check if a thread-safety bug is found
                if (trapObjects.ContainsKey(objectId))
                {
                    foreach (Trap trap in trapObjects[objectId])
                    {
                        ThreadSafetyInterceptionPoint runningTP = this.GetThreadSafetyInterceptionPoint(trap.InterceptionPoint);
                        if (threadSafetyInterceptionPoint.IsWriteAPI || runningTP.IsWriteAPI)
                        {
                            bugFound = true;
                            interceptionPoint.StackTrace = Environment.StackTrace;

                            // DebugLog.Log("HitBug " + InterceptionPoint.Tostring() + " " + runningt.InterceptionPoint.Tostring());
                            ControllerHelper.WriteBug(trap, interceptionPoint);
                            this.LogBugForNextRun(interceptionPoint, trap.InterceptionPoint);

                            // For some InterceptionPoints, keep execution even hitting a bug. It may expose more bugs.
                            if ((trapPlan != null) && (!trapPlan.Repeat))
                            {
                                continueAfterBug = true;
                            }
                        }
                    }
                }

                if (bugFound && (!continueAfterBug))
                {
                    // DebugLog.Log("HIt Bug and exit " + InterceptionPoint.Tostring());
                    return(null);
                }

                // else
                {
                    // check if the InterceptionPoint match with dangerous list
                    danger = this.IsInsideDangerList(interceptionPoint.Location);

                    if ((danger < 0) && (!interceptionPoint.IsInPlan))
                    {
                        // exit when not matching and not in the plan
                        return(null);
                    }

                    // prepare to set up a trap if (threadSafetyInterceptionPoint.IsWriteAPI && !this.isTrapActive)
                    if ((!this.isTrapActive || (danger >= 0) || interceptionPoint.IsInPlan) && ((trapPlan != null) || threadSafetyInterceptionPoint.IsWriteAPI))
                    {
                        prob = trapPlan != null ? trapPlan.DelayProbability : this.DelayProbability;

                        if (danger >= 0)
                        {
                            prob = this.DelayProbabilityAtDangerousInterceptionPoint - (this.DecayFactor * danger);
                        }

                        if (this.random.NextDouble() <= prob)
                        {
                            // Get stack trace only if setting up a trap.
                            interceptionPoint.StackTrace = Environment.StackTrace;

                            semaphore     = new Semaphore(0, 1);
                            sleepDuration = trapPlan == null?
                                            this.random.Next(this.MaxDelayPerInterceptionPoint)
                                                : trapPlan.FixedDelayMs;

                            if (danger >= 0)
                            {
                                sleepDuration = this.DelayPerDangerousInterceptionPoint;
                            }

                            newTrap = new Trap
                            {
                                ObjectId          = objectId,
                                Semaphore         = semaphore,
                                InterceptionPoint = interceptionPoint,
                                Delay             = sleepDuration,
                            };

                            ControllerHelper.WriteTrap(newTrap);

                            if (!trapObjects.ContainsKey(objectId))
                            {
                                trapObjects.Add(objectId, new HashSet <Trap>());
                            }

                            trapObjects[objectId].Add(newTrap);

                            this.isTrapActive = true;
                        }
                    }
                }
            }

            return(newTrap);
        }
示例#20
0
        /// <summary>
        /// Converts to rchpointstart.
        /// </summary>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        /// <param name="instance">The instance.</param>
        /// <param name="parameters">The parameters.</param>
        /// </summary>
        public void InterceptionPointStart(InterceptionPoint interceptionPoint, object instance = null, object[] parameters = null)
        {
            /*
             * I add more field variables to help the analysis. They are initialized in the constructor.
             * when hitting a new InterceptionPoint here are the procedures in the implementation:
             * 1.assign the hit-seq for InterceptionPoint
             * 2.assign the global id for InterceptionPoint. It is duplicated with InterceptionPoint.id.
             * 3.update the InterceptionPoints history to infer the concurrent threads.
             * 4.find the dangerous pair for this InterceptionPoint
             * 5.find the the opeartion set that happens-before this InterceptionPoint
             * 6.check if find a bug
             * 7.construct the trap
             * 8.execute the trap
             * 9.locate the threads that are blocked by this trap
             */
            var newBugFound = false;

            if (this.configuration == null || this.configuration.ThreadSafetyGroups == null)
            {
                return;
            }

            this.UpdateTPHitCounts(interceptionPoint);

            TrapPlan trapPlan = this.TrapPlans.FindMatchingPlan(interceptionPoint, this.GlobalHitcountWindow, this.LocalHitcountWindow);

            interceptionPoint.IsInPlan = trapPlan != null;

            this.UpdateTPHistory(interceptionPoint);

            // This block is used for monitoring the lock.Now we can just skip the lock operations. this.Updatelockinformation(InterceptionPoint);
            if (this.LockRelatedOP(interceptionPoint))
            {
                return;
            }

            // Locate the APIs bypass the lock operation
            ThreadSafetyInterceptionPoint threadSafetyInterceptionPoint = this.GetThreadSafetyInterceptionPoint(interceptionPoint);

            if (threadSafetyInterceptionPoint == null ||
                (!threadSafetyInterceptionPoint.ThreadSafetyGroup.IsStatic && instance == null))
            {
                return;
            }

            // update the write/read InterceptionPoint
            interceptionPoint.IsWrite = threadSafetyInterceptionPoint.IsWriteAPI;

            interceptionPoint.ObjID = threadSafetyInterceptionPoint.ThreadSafetyGroup.IsStatic ? ObjectId.GetRefId(null) : ObjectId.GetRefId(instance);

            // this block will looking for the near-miss pair and learn the dependency.
            if ((interceptionPoint.IsInPlan == false) && (this.DetectDangerousPairs == true))
            {
                this.FindRacingTP(interceptionPoint);
                this.RemoveDependentInterceptionPoints(interceptionPoint);
            }

            var trapObjects = this.GetTrapObjects(threadSafetyInterceptionPoint);

            Trap trap = this.CheckForBugsAndStartTrap(interceptionPoint, threadSafetyInterceptionPoint, trapObjects, trapPlan, instance, out newBugFound);

            if (trap == null)
            {
                return;
            }

            this.FinishTrap(trapObjects, trap, interceptionPoint);

            if (this.configuration.ThrowExceptionOnRace & newBugFound)
            {
                throw new Exception("ThreadSafety bugs detected by TSVD");
            }

            return;
        }
        /// <inheritdoc/>
        public void InterceptionPointStart(InterceptionPoint interceptionPoint, object instance = null, object[] parameters = null)
        {
            /*
             * if (!this.isTrapActive && bugFound)
             *  throw new Exception("ThreadSafety bugs detected by Torch");
             */
            bool newTrapsAllowed = true;
            bool newBugFound     = false;

            if (this.configuration == null || this.configuration.ThreadSafetyGroups == null)
            {
                return;
            }

            ThreadSafetyInterceptionPoint threadSafetyInterceptionPoint = ControllerHelper.GetThreadSafetyInterceptionPoint(this.configuration.ThreadSafetyGroups, interceptionPoint);

            if (threadSafetyInterceptionPoint == null)
            {
                return;
            }

            if (!threadSafetyInterceptionPoint.ThreadSafetyGroup.IsStatic && instance == null)
            {
                return;
            }

            string groupName = threadSafetyInterceptionPoint.ThreadSafetyGroup.Name;
            Dictionary <Guid, Trap> trapObjects = null;

            lock (this.trapPoints)
            {
                if (!this.trapPoints.ContainsKey(groupName))
                {
                    this.trapPoints.Add(groupName, new Dictionary <Guid, Trap>());
                    if (threadSafetyInterceptionPoint.IsWriteAPI)
                    {
                        this.writeTrapPoints.Add(groupName);
                    }
                }

                trapObjects = this.trapPoints[groupName];
            }

            Semaphore semaphore     = null;
            int       sleepDuration = 0;
            Guid      keyInstance   = ObjectId.GetRefId(null);

            lock (trapObjects)
            {
                if (!threadSafetyInterceptionPoint.ThreadSafetyGroup.IsStatic)
                {
                    keyInstance = ObjectId.GetRefId(instance);
                }

                // Check if a trap on this object is live
                Trap trap = null;
                trapObjects.TryGetValue(keyInstance, out trap);

                // A bug is found if there is a trap on this object and
                // either this access or trapped access is a write
                if (trap != null &&
                    (threadSafetyInterceptionPoint.IsWriteAPI ||
                     trap.ThreadSafetyInterceptionPoint.IsWriteAPI))
                {
                    // Get stack track when a bug is found.
                    interceptionPoint.StackTrace = Environment.StackTrace;
                    ControllerHelper.WriteBug(trap, interceptionPoint);
                    newBugFound = true;

                    try
                    {
                        trap.Semaphore.Release();
                    }
                    catch (SemaphoreFullException)
                    {
                    }
                }
                else if (newTrapsAllowed)
                {
                    // prepare to set up a trap
                    if (!this.isTrapActive)
                    {
                        if (threadSafetyInterceptionPoint.IsWriteAPI && this.random.NextDouble() <= this.DelayProbability)
                        {
                            // Get stack trace only if setting up a trap.
                            interceptionPoint.StackTrace = Environment.StackTrace;

                            semaphore     = new Semaphore(0, 1);
                            sleepDuration = this.random.Next(this.MaxDelayPerInterceptionPoint);

                            trap = new Trap
                            {
                                ObjectId                      = keyInstance.ToString(),
                                Semaphore                     = semaphore,
                                InterceptionPoint             = interceptionPoint,
                                ThreadSafetyInterceptionPoint = threadSafetyInterceptionPoint,
                                Delay = sleepDuration,
                            };

                            ControllerHelper.WriteTrap(trap);
                            trapObjects.Add(keyInstance, trap);
                            this.isTrapActive = true;
                        }
                    }
                }
            }

            if (semaphore != null)
            {
                semaphore.WaitOne(sleepDuration);

                lock (trapObjects)
                {
                    trapObjects.Remove(keyInstance);
                }

                this.isTrapActive = false;
            }

            if (this.configuration.ThrowExceptionOnRace && newBugFound)
            {
                throw new Exception("ThreadSafety bugs detected by Torch");
            }

            return;
        }