损坏的锁?魔术僵局? [英] Corrupted lock ? Magic deadlock?

查看:252
本文介绍了损坏的锁?魔术僵局?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作与multethreading错误。现在我看到,由于某种原因,锁不执行甚至不止一次,而是被锁定。我隔壁班的:

I work with multethreading bug. Now I see that for some reason lock isn't executed even once but is locked. I have the next class:

public sealed class Foo
{
       private readonly object _lock = new object();
       private static ulong _inCnt = 0;

    public void SomeMethod(ulong poo)
    {
        lock (_lock)
        {
           _inCnt++;
           ... [some code]
        }
    }
 }

我停顿了一下,在VS的所有线程,检查所有这些,看到有只有一个线程的someMethod ,它正在等待锁定(_lock)来释放(_ INCNT = 0)。 我恢复线程,等了一会儿,暂停线程,看到了同样的画面,相同的(也是唯一一个)线程仍然在<$等待锁(_lock) C C>的someMethod 和 _inCnt 是零! 但是,如果锁将永远entred( _inCnt ++ 是在的第一行锁这将是一个或多个(_lock)没有异常可以发生,我们不会放弃线程)。又岂是零,锁被锁定?

I paused all threads in the VS, inspected all of them and see that there is only one thread in the SomeMethod and it is waiting for lock (_lock) to be freed (_inCnt = 0). I resumed threads, waited for a while, paused threads and see the same picture, the same (and only one) thread is still waiting for the lock (_lock) in SomeMethod and _inCnt is zero! But it will be one or more if lock will be ever entred(_inCnt++ is the first line after lock (_lock) no exception can happens, we don't abort threads). How can it be zero and lock is locked?

推荐答案

如果您所有的假设是正确的,而你的真的确定,从来没有一个意外的线程终止,那么你必须考虑GC堆数据损坏。存储该锁定状态中System.Object的领域是相当脆弱的,它是在对象的第一场。因此,即使是温和的缓冲区溢出pinvoked本土code是容易覆盖领域,使CLR认为持有锁。

If all of your assumptions are correct, and you are really sure that there never was an unexpected thread abort, then you have to consider GC heap data corruption. The field in System.Object that stores the lock state is fairly vulnerable, it is the very first field in the object. So even a modest buffer overrun in pinvoked native code is liable to overwrite that field and make the CLR think that the lock is held.

假设是不过的undebuggable问题,无法回答的问题之母。最好进行检查,它实际上是可调试的。我会认为32位code执行。使用调试+快速监视和键入&放大器; _lock 。这使你的对象引用的地址。切换到调试+的Windows +内存+内存1,输入你获得的地址。右键单击该窗口中,选择4字节整数。现在可以看到的物体,它是存储在GC堆的地址。从这个数字中减去4,然后键入结果在地址框中。您现在可以看到,存储锁定状态的领域。它是0,如果锁定没有保持,如果它被保持,则它包含拥有锁的线程的Thread.ManagedId。您可以关联,要调试+的Windows +线程窗口。

Assumptions are however the mother of undebuggable problems and unanswerable questions. Best to check them, it is actually debuggable. I'll assume 32-bit code execution. Use Debug + QuickWatch and type &_lock. That gives you the address of the object reference. Switch to Debug + Windows + Memory + Memory1 and type the address you got. Right-click the window and select "4-byte integer". You'll now see the address of the object, where it is stored in the GC heap. Subtract 4 from that number and type the result in the Address box. You now see the field that stores the lock state. It is 0 if the lock isn't held, if it is held then it contains the Thread.ManagedId of the thread that owns the lock. You can correlate that to the Debug + Windows + Threads window.

三个基本方案:

  • 如果您发现该线程回到线程窗口,那么你已经有了一个僵局,你会在什么线程正在做什么很感兴趣。双击它,并期待在调用堆栈窗口,看看它为什么没有取得进展
  • 如果您不能找到线索那时你有一个非常强烈暗示你的code从意外线程中止事故患
  • 如果你看到一个奇怪的随机数,那么你已经得到了GC堆被损坏的情况。

这篇关于损坏的锁?魔术僵局?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆