Ken Birman
Ken Birman

Reputation: 1118

C# attempt to reentrantly lock something deadlocked, apparent bug

Curious to know if anyone else has seen this problem. I have an application that locks a statically declared object, this way:

lock(Group.IsisGroups)
{
          do some stuff 
}

do-some-stuff does various stuff and one of the routines I called attempts to lock the same lock. Thread deadlocks.

My guess is that this issue is somehow tied to my use of reflection: mid-way down the call stack I do a call to a method by looking it up in the class definition and calling .Invoke(). The call stack that results is this:

[In a sleep, wait, or join]  
[External Code]  
ConsoleApplication2.exe!Isis.Group.doLookup(Isis.Address gaddr) Line 3774 + 0x13 bytes  
ConsoleApplication2.exe!Isis.ReliableSender.GotIncoming(byte type, Isis.Address gaddr, Isis.Address sender, int minStable, Isis.Msg m) Line 10179 + 0x9 bytes  
ConsoleApplication2.exe!Isis.ReliableSender.doReceive.AnonymousMethod14(byte type, byte code, int seqn, int truePayLoadLen, int PreFragLen, Isis.Address sender, Isis.Address dest, Isis.Address gaddr, int minStable, int FID, int Fn, int nF, byte[] buf) Line 3120 + 0x80 bytes  
[External Code]  
ConsoleApplication2.exe!Isis.Msg.doInvokeSingle(System.Delegate del, byte[] barray, System.Type[] types) Line 11582 + 0x10 bytes  
ConsoleApplication2.exe!Isis.Msg.InvokeFromBArray(byte[] barray, System.Delegate del) Line 11527 + 0xf bytes  
ConsoleApplication2.exe!Isis.ReliableSender.doReceive(object os, Isis.Group g) Line 10034 + 0x71 bytes  
ConsoleApplication2.exe!Isis.ReliableSender.Receive(Isis.Group g) Line 10013 + 0xe bytes  
ConsoleApplication2.exe!Isis.ReliableSender.StartGroupReader.AnonymousMethod__6(object o) Line 9097 + 0xc bytes  
[External Code]  

So the initial call to lock(Group.IsisGroups) is in the top method on the stack ReliableSender.StartGroupReader and the code deadlocks when it calls lock in the bottom method, doLookup. The [External Code] blocks are from where I called the reflection Invoke() method, and from the call into lock() that caused things to deadlock. Definitely the same object being locked, etc (the object is statically allocated when my class is loaded and is of type List<Isis.Group> and while I do add and remove things, the actual List object remains througout.

Any suggestions on what could cause this?

Upvotes: 0

Views: 405

Answers (2)

Ken Birman
Ken Birman

Reputation: 1118

OK, don't feel like leaving this open, so my "answer" is this: First, (sorry) Bengie and Hans just don't seem to understand that sure enough, a reentrant lock is malfunctioning. Second, I suspect that this is happening because of my use of reflection; somehow the context information they use to realize that the lock is being re-locked by the same thread is apparently being impacted.

I'm going to fix this by changing my code to not hold the lock during the initial call; basically, I won't try to acquire this lock reentrantly.

Others who run into this thread should be warned: as far as I can tell, I'm encountering what can only be a .NET bug. And it isn't very hard to provoke, either.

Upvotes: 0

Bengie
Bengie

Reputation: 1035

Am I reading this correctly?

So the initial call to lock(Group.IsisGroups) is in the top method on the stack[...]and the code deadlocks when it calls lock in the bottom method[...]into lock() that caused things to deadlock.Definitely the same object being locked.

Some pseudo-code of your methods that shows how they lock would help, but based on what I read, it sounds like you lock the same object with-in the lock?

If I read this correctly, it sounds like this happened

lock(ob1)
{
  lock(ob1)
  {
  }
}

but you sound quite sure of yourself, so I'm assuming I'm mis-reading that.

either way, some pseudo-code of the methods calling the locks would be nice. :p

Deadlocks are caused by multiple methods/threads locking objects in a "wrong" order.

Upvotes: 1

Related Questions