BugCheck CA 가 발생했을 경우 가장 중요한 부분은 Pnp Manager의 PDO에 대한 Device Node를 찾는 경우 입니다. BugCheck CA의 90%이상이 PDO와 Device Node 사이의 상관 관계에서 발생하기 때문입니다. 간단한 예를 보도록 하죠.
1: kd> !analyze -v
… 생략
PNP_DETECTED_FATAL_ERROR (ca)
PnP encountered a severe error, either as a result of a problem in a driver or
a problem in PnP itself. The first argument describes the nature of the
problem, the second argument is the address of the PDO. The other arguments
vary depending on argument 1.
Arguments:
Arg1: 00000004, Invalid enumeration of deleted PDO
An enumerator has returned a PDO which it has previously deleted
using IoDeleteDevice.
Arg2: 888a18f0, PDO with DOE_DELETE_PENDING set.
Arg3: 00000000
Arg4: 00000000
Debugging Details:
——————
*** No owner thread found for resource 805624e0
*** No owner thread found for resource 805624e0
*** No owner thread found for resource 805624e0
*** No owner thread found for resource 805624e0
BUGCHECK_STR: 0xCA_4
DEVICE_OBJECT: 888a18f0
DRIVER_OBJECT: 8a6d74b0
IMAGE_NAME: PnpManager
DEBUG_FLR_IMAGE_TIMESTAMP: 0
MODULE_NAME: PnpManager
FAULTING_MODULE: 00000000
DEFAULT_BUCKET_ID: DRIVER_FAULT
PROCESS_NAME: System
LOCK_ADDRESS: 80562560 — (!locks 80562560)
Resource @ nt!IopDeviceTreeLock (0×80562560) Shared 1 owning threads
Contention Count = 2
Threads: 8a6ec640-01<*>
1 total locks, 1 locks currently held
PNP_TRIAGE:
Lock address : 0×80562560
Thread Count : 1
Thread address: 0×8a6ec640
Thread wait : 0×1c3248
LAST_CONTROL_TRANSFER: from 80522fa2 to 805393aa
STACK_TEXT:
f78deaa0 80522fa2 000000ca 00000004 888a18f0 nt!KeBugCheckEx+0×1b
f78deacc 805a14b3 00000005 88156928 8a6d6ee8 nt!PipEnumerateCompleted+0×28c
f78ded20 805a15ef 8a6d6ee8 00000001 00000000 nt!PipProcessDevNodeTree+0×2a9
f78ded54 8050eeae 00000003 805625c0 8056b4fc nt!PiProcessReenumeration+0×60
f78ded7c 804e43b5 00000000 00000000 8a6ec640 nt!PipDeviceActionWorker+0×170
f78dedac 80576120 00000000 00000000 00000000 nt!ExpWorkerThread+0xef
f78deddc 804ee781 804e42f1 00000001 00000000 nt!PspSystemThreadStartup+0×34
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0×16
STACK_COMMAND: kb
FOLLOWUP_NAME: MachineOwner
FAILURE_BUCKET_ID: 0xCA_4_IMAGE_PnpManager
BUCKET_ID: 0xCA_4_IMAGE_PnpManager
Followup: MachineOwner
———
PDO의 Status( Extension Flag )에 DOE_DELETE_PENDING 이 Mark 되어 있어서 발생한 상황임을 알 수 있습니다. 즉 PDO와 Link된 Driver가 정상적으로 Unload 되지 않아 Pending 상태가 발생했다고 볼 수 있습니다.
1: kd> !devobj ffffffff888a18f0 f
Device object (888a18f0) is for:
\Driver\PnpManager DriverObject 8a6d74b0
Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040
Dacl e177b774 DevExt 888a19a8 DevObjExt 888a19b0 DevNode 889d9ee8
ExtensionFlags (0×00000012) DOE_DELETE_PENDING, DOE_START_PENDING
Device queue is not busy.
PDO의 Device Object 정보를 보면 해당 DeviceNode를 볼 수 있수 있습니다. Device Node의 정보를 통해서 어떤 드라이버가 정상적으로 Unload 되지 않았는지 확인하면 되겠군요.
1: kd> !devobj ffffffff888a18f0 f
Device object (888a18f0) is for:
\Driver\PnpManager DriverObject 8a6d74b0
Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040
Dacl e177b774 DevExt 888a19a8 DevObjExt 888a19b0 DevNode 889d9ee8
ExtensionFlags (0×00000012) DOE_DELETE_PENDING, DOE_START_PENDING
Device queue is not busy.
1: kd> !devnode 889d9ee8
DevNode 0×889d9ee8 for PDO 0×888a18f0
Parent 0×8a6d6ee8 Sibling 0×88a44a08 Child 0000000000
InstancePath is “Root\LEGACY_MyDrv\0000″
ServiceName is “MyDrv”
State = DeviceNodeRemoved (0×312)
Previous State = DeviceNodeStarted (0×308)
StateHistory[02] = DeviceNodeStarted (0×308)
StateHistory[01] = DeviceNodeInitialized (0×302)
StateHistory[00] = DeviceNodeUninitialized (0×301)
StateHistory[19] = Unknown State (0×0)
StateHistory[18] = Unknown State (0×0)
StateHistory[17] = Unknown State (0×0)
StateHistory[16] = Unknown State (0×0)
StateHistory[15] = Unknown State (0×0)
StateHistory[14] = Unknown State (0×0)
StateHistory[13] = Unknown State (0×0)
StateHistory[12] = Unknown State (0×0)
StateHistory[11] = Unknown State (0×0)
StateHistory[10] = Unknown State (0×0)
StateHistory[09] = Unknown State (0×0)
StateHistory[08] = Unknown State (0×0)
StateHistory[07] = Unknown State (0×0)
StateHistory[06] = Unknown State (0×0)
StateHistory[05] = Unknown State (0×0)
StateHistory[04] = Unknown State (0×0)
StateHistory[03] = Unknown State (0×0)
Flags (0×00003101) DNF_MADEUP, DNF_NO_RESOURCE_REQUIRED,
DNF_LEGACY_DRIVER, DNF_HAS_PROBLEM
UserFlags (0×00000001) DNUF_WILL_BE_REMOVED
Problem = CM_PROB_DEVICE_NOT_THERE
MyDrv라는 녀석이 정상적으로 Unload 되지 않았을 것이라 추정할 수 있습니다. 하지만 현재 DeviceNode의 State는 DeviceNodeRemoved로 표시 되어 있는 것을 확인 할 수 있습니다. 이러한 이유에서 ReEnumeration이 발생했을때 DeviceNode가 Removed 되어진 것으로 알고 PDO를 재사용하려다 DOE_DELETE_PENDING 상태이기 때문에 BugCheck 발생하게 된거죠.
해당 Driver의 Device Object를 확인해 보면 좀더 명확히 Unload Pending 여부를 확인 할 수 있습니다.
1: kd> !devobj \device\MyDrv
Device object (88a57030) is for:
\Driver\MyDrv DriverObject 88d92d60
Current Irp 00000000 RefCount 0 Type 00000022 Flags 00000844
Dacl e177b774 DevExt 88a570e8 DevObjExt 88a570f0
ExtensionFlags (0×00000001) DOE_UNLOAD_PENDING
Device queue is not busy.
이제 드라이버 Unload 로직을 체크해보면 좀더 정확한 답을 얻을 수 있을 것 같군요 .
Enjoy Debugging

최근 답글