/// <summary> /// Check if the current message will cause deadlock. /// Throw DeadlockException if yes. /// </summary> /// <param name="message">Message to analyze</param> private void CheckDeadlock(Message message) { object obj = message.GetApplicationHeader(RequestContext.CALL_CHAIN_REQUEST_CONTEXT_HEADER); if (obj == null) { return; // first call in a chain } var prevChain = ((IList)obj); ActivationId nextActivationId = message.TargetActivation; // check if the target activation already appears in the call chain. foreach (object invocationObj in prevChain) { var prevId = ((RequestInvocationHistory)invocationObj).ActivationId; if (!prevId.Equals(nextActivationId) || catalog.IsReentrantGrain(nextActivationId)) { continue; } var newChain = new List <RequestInvocationHistory>(); newChain.AddRange(prevChain.Cast <RequestInvocationHistory>()); newChain.Add(new RequestInvocationHistory(message)); throw new DeadlockException(newChain.Select(req => new Tuple <GrainId, int, int>(req.GrainId, req.InterfaceId, req.MethodId)).ToList()); } }