Friday, February 13, 2009

Another goody: uf /c /D and the peb lock

Remember my previous post?

I was hunting a dead lock and found the good old 6.7.5.0 again worth keeping.

But I didn't write about the dead lock cause itself. Now here it comes:

 

The main thread was waiting for the peb lock:

0:00> ~0 kb
ChildEBP RetAddr Args to Child
0012c72c 7c90e9c0 7c91901b 0000056c 00000000 ntdll!KiFastSystemCallRet
0012c730 7c91901b 0000056c 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
0012c7b8 7c90104b 0097e4c0 7c910945 7c97e4c0 ntdll!RtlpWaitForCriticalSection+0x132
0012c7c0 7c910945 7c97e4c0 ffffffff 00000000 ntdll!RtlEnterCriticalSection+0x46
0012c800 7c80e2cf ffffffff 7c80e038 00000000 ntdll!RtlAcquirePebLock+0x28
0012c868 7c80e00d 7c80e038 00020690 00000000 kernel32!BasepComputeProcessPath+0x5f
0012c8a8 7c801b83 00000000 00000000 0012d7a0 kernel32!BaseComputeProcessDllPath+0xe3
0012c908 7c801d6e 7ffdfc00 00000000 00000000 kernel32!LoadLibraryExW+0x12f
0012c91c 7c801da4 06057954 00000000 00000000 kernel32!LoadLibraryExA+0x1f
0012c938 060b4823 06057954 7c911993 03f41ea8 kernel32!LoadLibraryA+0x94

 

This lock was owned by managed thread number 6:

0:006> k 100
ChildEBP RetAddr 
0522f33c 7c9141e4 ntdll!RtlGetFullPathName_Ustr+0x653
0522f364 7c80b86c ntdll!RtlGetFullPathName_U+0x33
0522f37c 015da1c3 kernel32!GetFullPathNameW+0x1a
0522f3a4 79364aef CLRStub[StubLinkStub]@15da1c3
0522f8f0 793644ae mscorlib_ni!System.IO.Path.NormalizePathFast(System.String, Boolean)+0x637
017d2738 793821b0 mscorlib_ni!System.IO.Path.GetFullPathInternal(System.String)+0x2e
017d2738 793820f6 mscorlib_ni!System.Security.Util.StringExpressionSet.CanonicalizePath(System.String, Boolean)+0x90
017d2738 79381dbe mscorlib_ni!System.Security.Util.StringExpressionSet.CreateListFromExpressions(System.String[], Boolean)+0x14a
017d2738 79381d16 mscorlib_ni!System.Security.Permissions.FileIOPermission.AddPathList(System.Security.Permissions.FileIOPermissionAccess, System.Security.AccessControl.AccessControlActions, System.String[], Boolean, Boolean, Boolean)+0x6a
0178b9ec 793a2014 mscorlib_ni!System.Security.Permissions.FileIOPermission..ctor(System.Security.Permissions.FileIOPermissionAccess, System.String)+0x42
0522f978 04189669 mscorlib_ni!System.IO.FileSystemInfo.get_FullName()+0x58
0177cdbc 041892b2 XYZ.DirectoryCleanup.PopulateAllFilesList(System.Collections.Generic.List`1<System.IO.FileInfo>, System.IO.DirectoryInfo)+0x69
0522fa00 0418916f XYZ.DirectoryCleanup.CleanupThread()+0xaa
0522fa30 79407caa XYZ.DirectoryCleanup.CleanupThreadProc(System.Object)+0x67
0179439c 79373ecd mscorlib_ni!System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(System.Object)+0x1a
0179439c 79407e18 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x81
0522fa60 79407d90 mscorlib_ni!System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(System.Threading._ThreadPoolWaitCallback)+0x50
1f7814b0 79e7c74b mscorlib_ni!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(System.Object)+0x60
0522fa84 79e7c6cc mscorwks!CallDescrWorker+0x33
0522fb04 79f00eca mscorwks!CallDescrWorkerWithHandler+0xa3
0522fb24 79f00e75 mscorwks!DispatchCallBody+0x1e
0522fb88 79f00f03 mscorwks!DispatchCallDebuggerWrapper+0x3d
0522fbbc 79f6e39d mscorwks!DispatchCallNoEH+0x51
0522fc1c 79ef3207 mscorwks!QueueUserWorkItemManagedCallback+0x6c
0522fc30 79ef31a3 mscorwks!Thread::DoADCallBack+0x32a
0522fcc4 79ef30c3 mscorwks!Thread::ShouldChangeAbortToUnload+0xe3
0522fd00 79ef4826 mscorwks!Thread::ShouldChangeAbortToUnload+0x30a
0522fd28 79ef48cf mscorwks!Thread::ShouldChangeAbortToUnload+0x33e
0522fd40 79f6e2d8 mscorwks!ManagedThreadBase::ThreadPool+0x13
0522fda8 79f0202a mscorwks!ManagedPerAppDomainTPCount::DispatchWorkItem+0xdb
0522fdbc 79f021a0 mscorwks!ThreadpoolMgr::ExecuteWorkRequest+0xaf
0522fe14 79f95a2e mscorwks!ThreadpoolMgr::WorkerThreadStart+0x223
0522ffb4 7c80b683 mscorwks!Thread::intermediateThreadProc+0x49
0522ffec 00000000 kernel32!BaseThreadStart+0x37

Now my question was: Does kernel32!GetFullPathNameW acquire a peb lock?

The short answer is yes (in Windows XP but not in Vista).

Here's the easy way to find out with uf /c /D (/D creates linked callee names for navigation of the call graph. Do you can click on the hyperlinks ;-) ):

0:006> uf /c /D kernel32!GetFullPathNameW
kernel32!GetFullPathNameW (7c80b852)
  kernel32!GetFullPathNameW+0x14 (7c80b866):
   
call to ntdll!RtlGetFullPathName_U (7c9141b1)

0:006> uf /c /D 0x7c9141b1
ntdll!RtlGetFullPathName_U (7c9141b1)
  ntdll!RtlGetFullPathName_U+0xe (7c9141bf):
    call to ntdll!RtlInitUnicodeStringEx (7c9103a5)
  ntdll!RtlGetFullPathName_U+0x2e (7c9141df):
    call to ntdll!RtlGetFullPathName_Ustr (7c913b67)

0:006> uf /c /D 0x7c913b67
ntdll!RtlGetFullPathName_Ustr (7c913b67)
  ntdll!RtlGetFullPathName_Ustr+0xa (7c913b71):
    call to ntdll!_SEH_prolog (7c90edc2)
  ntdll!RtlGetFullPathName_Ustr+0xbe (7c913c19):
    call to ntdll!RtlIsDosDeviceName_Ustr (7c9139ed)
  ntdll!RtlGetFullPathName_Ustr+0x176 (7c913c59):
    call to ntdll!RtlDetermineDosPathNameType_U (7c91399f)
  ntdll!RtlGetFullPathName_Ustr+0x180 (7c913c63):
    call to ntdll!RtlAcquirePebLock (7c91091d) <== Here you go
[...]

 

Doing the same on Vista shows no PebLock

0:003> uf /c /D kernel32!GetFullPathNameW
KERNEL32!GetFullPathNameW (77c60a0e)
  KERNEL32!GetFullPathNameW+0x14 (77c60a22):
    call to ntdll!RtlGetFullPathName_U (77b0ac1f)
0:003> uf /c /D 0x77b0ac1f
ntdll!RtlGetFullPathName_U (77b0ac1f)
  ntdll!RtlGetFullPathName_U+0xe (77b0ac2d):
    call to ntdll!RtlInitUnicodeStringEx (77b09b9f)
  ntdll!RtlGetFullPathName_U+0x2e (77b0ac4d):
    call to ntdll!RtlGetFullPathName_Ustr (77b0a01f)
0:003> uf /c /D 0x77b0a01f
ntdll!RtlGetFullPathName_Ustr (77b0a01f)
  ntdll!RtlGetFullPathName_Ustr+0x270 (77aaa47d):
    call to ntdll!RtlpReferenceCurrentDirectory (77b0aed5)
  ntdll!RtlGetFullPathName_Ustr+0x2a3 (77aaa497):
    call to ntdll!RtlpComputeBackupIndex (77b0af83)
  ntdll!RtlGetFullPathName_Ustr+0x2f9 (77ab0340):
    call to ntdll!RtlpReferenceCurrentDirectory (77b0aed5)
  ntdll!RtlGetFullPathName_Ustr+0x32b (77ab0366):
    call to ntdll!RtlUpcaseUnicodeChar (77ae0db2)
  ntdll!RtlGetFullPathName_Ustr+0x339 (77ab0374):
    call to ntdll!RtlUpcaseUnicodeChar (77ae0db2)
  ntdll!RtlGetFullPathName_Ustr+0x366 (77ab0386):
    call to ntdll!RtlpCheckRelativeDrive (77ab040c)
  ntdll!RtlGetFullPathName_Ustr+0x38c (77ab03ac):
    call to ntdll!RtlInitUnicodeString (77ae7e70)
  ntdll!RtlGetFullPathName_Ustr+0x3a9 (77ab03c9):
    call to ntdll!RtlQueryEnvironmentVariable_U (77ad4c19)
  ntdll!RtlGetFullPathName_Ustr+0x11e (77ad8154):
    call to ntdll!memmove (77ae8d80)
  ntdll!RtlGetFullPathName_Ustr+0x7 (77b0a026):
    call to ntdll!_SEH_prolog4_GS (77b08f60)
  ntdll!RtlGetFullPathName_Ustr+0xb0 (77b0a0c3):
    call to ntdll!RtlIsDosDeviceName_Ustr (77b09bf1)
  ntdll!RtlGetFullPathName_Ustr+0x15e (77b0a0e7):
    call to ntdll!memset (77ae90c0)
  ntdll!RtlGetFullPathName_Ustr+0x16a (77b0a0f3):
    call to ntdll!RtlDetermineDosPathNameType_Ustr (77b08ed3)
  ntdll!RtlGetFullPathName_Ustr+0x83e (77b0a27d):
    call to ntdll!RtlGetFullPathName_Ustr+0x84b (77b0a292)
  ntdll!RtlGetFullPathName_Ustr+0x141 (77b0a285):
    call to ntdll!_SEH_epilog4_GS (77b08fa8)
  ntdll!RtlGetFullPathName_Ustr+0x21b (77b0ae76):
    call to ntdll!RtlpReferenceCurrentDirectory (77b0aed5)
  ntdll!RtlGetFullPathName_Ustr+0x261 (77b0aea0):
    call to ntdll!RtlpComputeBackupIndex (77b0af83)
  ntdll!RtlGetFullPathName_Ustr+0xe9 (77b10822):
    call to ntdll!RtlpCheckDeviceName (77b2cf1c)
  ntdll!RtlGetFullPathName_Ustr+0x3f2 (77b1093d):
    call to ntdll!RtlInitUnicodeString (77ae7e70)

 

Many guys are offending Vista for this and that (mainly UAC stuff which sometimes really sucks) but for me this is another prove that Vista behaves more stable than previous Windows versions.

No comments: