 |
|
|
 |
|
 |
Hi. I just tried using this yesterday on an application that sporadically deadlocks. I added incslock.cs to my project and referenced the dll. I compiled the project and ran it. I did not get any stack trace files in the working directory.
Since I was not sure if the trace files would be output only when a potential / actual deadlock scenario is detected, I created a new project that definitely causes a deadlock. I included the files to this project and ran it. Still I dont get any trace files.
I guess I must be missing something basic here since its working for everyone else.
The code to simulate the deadlock is below (in case its relevant).
I would appreciate any help.
Thanks!
--------------------------------------------------------------------------------------
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading;
namespace CreatADeadlock { public partial class Deadlock : Form { private object _lockObject1 = new object(); private object _lockObject2 = new object();
public Deadlock() { InitializeComponent(); }
private void btnCreateDeadlock_Click(object sender, EventArgs e) { Thread th1 = new Thread(Thread1Execution); th1.Name = "Thread 1"; th1.Start();
MainThreadExecution(); }
private void Thread1Execution() { lock (_lockObject1) { Thread.Sleep(10 * 1000);
lock (_lockObject2) { ; }
}
}
private void MainThreadExecution() { lock (_lockObject2) { Thread.Sleep(10 * 1000);
lock (_lockObject1) { ; }
}
} } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Let's start with why your example doesn't produce traces - the reason is that you create a 100% deadlock... You can read the explanation of why one cannot detect a 100% deadlock either in the article or in my response to the first post.
Anyway according to the fact use System.Collections.Generic I assume you are trying to work with .Net 2.0. As I wrote as response to another post, this demands some workaround since .Net 2 doesn't allow the trick of overriding the default system class... Read my response to the post about .Net 2.0 and you will be able to detect your deadlocks...
If you need any further assistance let me know.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I'm programming in native c++. (VS6) I'm having a dead lock problems too and i don't have a clue where to start looking. I want to use your idea to solve my problem, and rewrite it in native c++. Can you upload the complete source code.
Or contact me on the mail: evyatarap@gmail.com.
Thanks in advanced, Evyatar.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
I enhanced the code a little bit to facilitate the switch-over of lock() blocks. Each 'lock(obj)' line is replaced with 'using (Monitor.Lock(obj))'. The 'using' statement ensures that the Monitor is properly exited no matter whether an exception is thrown or not, thereby keeping the semantics of the 'lock' block. If you have a regex-capable replacement tool, you should be done in no time.
public static IDisposable Lock(object obj) { return new LockContainer(obj); }
class LockContainer : IDisposable { object m_Object;
public LockContainer(object obj) { m_Object = obj; if (obj != null) slockimp.imp.DoLock(obj); }
public void Dispose() { if (m_Object != null) slockimp.imp.DoUnlock(m_Object); } }
Great work. I'm keeping my fingers crossed your DLL will help me finding a tricky deadlock situation.
Christoph
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
I tried to compile the code with Visual Studio 2008, but kept on getting the warning, stating that the compiler rather used the references from mscorlib. I've read up on it, and it seems that you have to compile your application with /nostdlib. How can I get the compiler to compile using /nostdlib in a web application?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
without using the standard libraries you need to define some basic classes as System.Object by yourself. This /nostdlib flag tells the compiler not to reference mscorlib. Since I haven't found an easy way to tell the compiler to prefer my version of System.Threading.Monitor, I would use the search/replace I suggested in one of the threads below.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Sorry, as I did suspect, you slockimp2 code does not detect indirect deadlock of dining philosophers, either. This is too bad, really, that I cannot see your source code, but -- frankly -- I simply don't know good criteria to detect this condition in any essentially universal way.
Please see my sample code below. I tried to make it as simple as I can. It can work as a console application just one source file.
First, I made sure I'm using your monitor, not the default System.Threading.Monitor, so I renamed it to Debug.Threading (included in my sample below). I also used slockimp.imp directly (2 lines below, commented out). (By the way your trick with replacement of the class using same namespace does not always work: in my VS2005 solution make issues a warning with notification saying the default System.Threading.Monitor was used, so I renamed the namespace.)
I used only two philosophers, which is enough to show the issue, and a simplest form of the Fork code. Anyway, the deadlock is clearly demonstrated, as well as the inability of your slockimp2 to give it any help.
Could you please analyze this with my sample and give us your ideas? Thank you.
 ////////////// CODE SAMPLE
using System;
namespace Debug.Threading { using System.Threading; class Monitor { public static void Enter(object obj) { slockimp.imp.DoLock(obj); } //Enter public static void Exit(object obj) { slockimp.imp.DoUnlock(obj); } //Exit public static bool TryEnter(object obj) { return slockimp.imp.DoTryEnter(obj); } //TryEnter public static bool TryEnter(object obj, int millisecondsTimeout) { return slockimp.imp.DoTryEnter(obj, millisecondsTimeout); } //TryEnter public static bool TryEnter(object obj, TimeSpan timeout) { return slockimp.imp.DoTryEnter(obj, timeout); } //TryEnter } //Monitor } //namespace Debug.Threading
namespace DiningPhilosophers { using System.Text; using System.Threading;
internal class Player { internal Player(string name) { this.Name = name; } internal void ShowNamedMessage(string format) { Console.WriteLine(string.Format(format, this.Name)); } //ShowNamedMessage string Name; } //Player
internal class Fork : Player { internal Fork(string name) : base(name) {} internal void PickUp() { Debug.Threading.Monitor.Enter(this); //slockimp.imp.DoLock(this); ShowNamedMessage("Fork {0} is taken"); Thread.Sleep(1000); //SA!!! this is done to ensure deadlock in a very first iteration } //PickUp internal void PutDown() { Debug.Threading.Monitor.Exit(this); //slockimp.imp.DoUnlock(this); ShowNamedMessage("Fork {0} is put down"); } //PutDown } //class Fork
internal class Philosopher : Player { internal Philosopher(string name, Fork left, Fork right) : base(name) { this.Left = left; this.Right = right; Thread = new Thread(delegate() { while (true) { Think(); Left.PickUp(); Right.PickUp(); Eat(); Left.PutDown(); Right.PutDown(); } //loop }); } //Philosopher internal void Start() { this.Thread.Start(); } void Eat() { ShowNamedMessage("Philosopher {0} is eating"); } //Eat void Think() { ShowNamedMessage("Philosopher {0} is thinking"); } //Think Thread Thread; Fork Left, Right; } //class Philosopher
class Program { static void Main(string[] args) { Console.WriteLine("Process started"); Fork fA = new Fork("A"); Fork fB = new Fork("B"); Philosopher pA = new Philosopher("A", fA, fB); Philosopher pB = new Philosopher("B", fB, fA); pA.Start(); pB.Start(); Console.ReadKey(); } //Main } //class Program
} //namespace DiningPhilosophers
////////////// END OF CODE SAMPLE
Thank you very much.
Sergey A Kryukov
|
| Sign In·View Thread·PermaLink | 3.67/5 (2 votes) |
|
|
|
 |
|
 |
Sergey,
Please read my answer to SAM below. The DLL can not prevent a deadlock once it happens, and you made sure in your code that it will happen.
Its purpose is to make the cases in which the deadlock does not happen 99.9% of the time (the hardest deadlocks to find, that occur at your customer site but never at your lab) and alert about them at your lab. In my answer to SAM I explained the rational of this behavior, and suggested him with a way to detect deadlocks that always happen with the DLL.
Assume thread 1 wants to lock A then B, and tread 2 wants to lock B then A. Assume in the first thread you already locked A. Now your second thread locks B. Now the second thread is about to lock A. I can not declare a deadlock here since nothing wrong in this scenario (yet, since I am not aware to thread 1’s intentions to lock B). So the code continues and a try to lock A is made, but then this lock will cause my data-structure protecting lock to stay locked, and the first thread (if it wishes to go on and lock B) will get stuck on my DS lock). Not protecting my DS is not an option since then false deadlock will be detected and also true potential deadlocks may not be detected.
Regarding VS 2005 this is true. Please read my suggestions to mickridgway2 bellow.
Eran
modified on Saturday, August 9, 2008 3:42 AM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
One additional remark about my suggestion to SAM below. If you are planing on using timeouts it will increase the chance of detecting the possible deadlock, but in order for the DLL to successfully detect it the problematic locks must be able to lock at least once! If I will take your example and repeatedly try it even with timeouts there is a good chance it won't detect the deadlock. But usually this won't be the case in most software.
In addition a 100% deadlock can usually be easily detected during development since I assume you execute parts of your code during development so it is easy to detect which new methods/locks created the deadlock.
Eran
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Can it detect more complex cases than a textbook case of the deadlock which is possible with just two thread and one lock/semaphore? How about the dining philosophers problem and other more complex cases? Thank you.
Sergey A Kryukov
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Sergey,
Thank you for your important question. The original posted file did not handle this issue since it was created in order to quickly find such a text-book case in short time due to a proble in an existing code that misbehaved. Nevertheless your remark is important so I uploaded a second file that should deal also with an indirect circular lock.
Eran
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Wow! Eran, thank you very much for such a quick and productive reply. Now, I should give it a try. Thanks again.
Sergey A Kryukov http://www.SAKryukov.org
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
No problem. Keep in mind it wasn't tested enough but I think it should be fine.
-- modified at 16:25 Tuesday 18th September, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi there,
I am getting:
The predefined type 'System.Threading.Monitor' is defined in multiple assemblies in the global alias; using definition from 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll'
I am on .NET 2.0 using VS2005sp1.
Is there something I am missing?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi,
This is the "trick": you should be able to make the compiler use the Monitor that is defined in the cs file (included in the zip). In VS 2003 the compiler warns you about it and says that it chose the newer version (that is not the one in mscorlib).
For VS2005 (or .net 2) you should be able to go around this using aliases, I never tried it but I think it should not be a problem to get the compiler use the incslock.cs version intead of its default mscorlib. Let me know if you are having problems.
Eran
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I can't seem to get the compiler to every use the version incslock.cs. It always chooses mscorlib.
Any ideas on how to get this going with aliases?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi,
Well I didn't have much time to explore this issue, but if you can't find the way to do it then I would suggest the following:
Rename the namespace in the incslock.cs file I uploaded (System -> _System). use Monitor = _System.Thread.Monitor
This will solve the issue only if you are using a direct Monitor.SomeLockMethod. As for the lock keyword: since it is a syntactic sugar to the full path System.Threading.Monitor I would suggest search-replace it within your entire code with a TimedLock - style lock (google it). This way you will still have the robustness of the try..finally that the lock keyword hides and in the implementation use the _System.Threading.Monitor version (or use Monitor =...).
Sorry for not finding an easier solution, but if I'll find something I will update later on.
-- modified at 15:51 Thursday 18th October, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Eransha,
I too am running into this issue, but your workarounds don't work for my project and what I need.
First, my project is in VS2005, and like the previous poster, I get:
Warning : The predefined type 'System.Threading.Monitor' is defined in multiple assemblies in the global alias; using definition from 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll'
...so the official/unmodified version is being used, not the incslock version, and I don't see any mechanism to override this and force the linker to use the incslock version.
Second, my app doesn't directly use Monitor or call Monitor.Enter, so your suggestion of renaming the namespace to _System and calling _System.Thread.Monitor isn't a work around I can use.
Any suggestions? Can you look into this? It's a good article, but due to this I can't use it.
Thanks,
Jeff
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Jeff,
I guess your code uses the "lock" clause, as I suggested in my previous answer you should be able to automatically search and replace all "lock" keywords into a kind of TimeLock pattern using the using keyword.
e.g. if your code looks like this:
lock(someobject) { }
It will look like this:
using (TimedLock.Lock(someobject)) { }
with the VS2005 IDE search & replace it should be done easily.
In your implementation of the TimedLock, use explicitly the _Monitor version rather than the Monitor of mscorlib.
Hope that helped, Eran
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
No can do. Yes, search & replace is simple, but with the project I'm working on, we're not using lock(). We're using a mix of background threads and Event threads. I've seen some locking going on in the UI (in the UI, when a UI thread gets locked) at times, and it would be nice if there was a tool that was able to point out when a deadlock or a blocking occurs, but we're not using lock().
Thanks,
Jeff
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |