当前位置:首页 > Windows程序 > 正文

WPF内部DeliverEvent读锁和PrivateAddListener写锁导致死锁

2021-05-23 Windows程序

1.对失去响应进程创建转储文件

2.配置该进程的pdb文件

3.复制该进程所在机器的系统dll(sos.dll, clr.dll, mscordacwks.dll)

4.配置系统dll的pdb文件路径, 或者直接从msdl.microsoft/download/symbols下载(注意端口是否被封)



分析过程:

1.利用~*e !clrstack

得到UI线程的ID 为12

2.利用~12e !clrstack -p

得到堆栈信息及函数参数值

3.从中发现先申请写锁, 后申请读锁,导致UI死锁

第一个锁CollectionChangedEventManager.DeliverEvent读锁

第二个锁PropertyChangedEventManager.PrivateAddListener写锁


0000000021137b28 000007fef87010b4 [HelperMethodFrame_1OBJ: 0000000021137b28] System.Threading.ReaderWriterLock.AcquireReaderLockInternal(Int32)
0000000021137c50 000007fef3eee179 System.Windows.WeakEventManager.DeliverEvent(System.Object, System.EventArgs)
    PARAMETERS:
        this (0x0000000021137ce0) = 0x0000000002f45678
        sender (0x0000000021137ce8) = 0x00000000039ac078
        args (0x0000000021137cf0) = 0x00000000044a2828


.....................省略部分日志信息


000000002113cf78 000007fef879cae7 [HelperMethodFrame_1OBJ: 000000002113cf78] System.Threading.ReaderWriterLock.AcquireWriterLockInternal(Int32)

000000002113d0a0 000007fef3eedf0a System.ComponentModel.PropertyChangedEventManager.PrivateAddListener(System.ComponentModel.INotifyPropertyChanged, System.Windows.IWeakEventListener, System.String)
    PARAMETERS:
        this = <no data>
        source = <no data>
        listener = <no data>
        propertyName = <no data>

000000002113d120 000007fee7ce8e76 MS.Internal.Data.PropertyPathWorker.ReplaceItem(Int32, System.Object, System.Object)
    PARAMETERS:
        this = <no data>
        k = <no data>
        newO = <no data>
        parent = <no data>


4. 利用!do分析读锁中DeliverEvent传递的参数args (0x0000000021137cf0) = 0x00000000044a2828

0:000> !do 0x00000000044a2828
Name:        System.Collections.Specialized.NotifyCollectionChangedEventArgs
MethodTable: 000007fef6b5ffb8
EEClass:     000007fef6853e90
Size:        48(0x30) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000007fef7840c78  40001c7       80     System.EventArgs  0   shared           static Empty
                                 >> Domain:Value  00000000007f85a0:0000000002f2a5c8 <<
000007fef6b5cad0  4000674       18         System.Int32  1 instance                4 _action
000007fef782f780  4000675        8 ...Collections.IList  0 instance 0000000000000000 _newItems
000007fef782f780  4000676       10 ...Collections.IList  0 instance 0000000000000000 _oldItems
000007fef782c858  4000677       1c         System.Int32  1 instance               -1 _newStartingIndex
000007fef782c858  4000678       20         System.Int32  1 instance               -1 _oldStartingIndex


5.根据成员_action 为4 查MSDN可知,当时的操作位Rest

public enum NotifyCollectionChangedAction

  {

    [__DynamicallyInvokable] Add,

    [__DynamicallyInvokable] Remove,

    [__DynamicallyInvokable] Replace,

    [__DynamicallyInvokable] Move,

    [__DynamicallyInvokable] Reset,

  }


6.通过~12e !dso 

得到对象名的堆栈信息

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/70008.html