Exemplo n.º 1
0
void ParseThread(DWORD TID) 
{
   WAITCHAIN_NODE_INFO chain[WCT_MAX_NODE_COUNT];

   DWORD dwNodesInChain;
   BOOL bDeadlock;
   dwNodesInChain = WCT_MAX_NODE_COUNT;
   DWORD dwNodeCount;

   /* Open thread wait chain session */
   HWCT hWCTSession = OpenThreadWaitChainSession(0, NULL);

   /* Get the chain for the current thread
    * Retrieves the wait chain for the specified thread.
	*
	* WctHandle [in]
    *  A handle to the WCT session created by 
	*  the OpenThreadWaitChainSession function.
	*
	* Context [in, optional]
    *  A pointer to an application-defined context structure 
	*  to be passed to the callback function for an asynchronous session.
	* 
	* Flags [in]
    *  The wait chain retrieval options.
	*  This parameter can be one of more of the following values.
	*           Value	                               Meaning
    *  WCT_OUT_OF_PROC_COM_FLAG	         Enumerates all threads of an out-of-proc MTA 
	*                                    COM server to find the correct thread identifier.
	*  
	*  WCT_OUT_OF_PROC_CS_FLAG	         Retrieves critical-section information from other processes.
	*
	*  WCT_OUT_OF_PROC_FLAG	             Follows the wait chain into other processes. 
	*                                    Otherwise, the function reports the first thread 
	*                                    in a different process but does not retrieve additional information.
	* ThreadId [in]
    *  The identifier of the thread. 
	* 
	* NodeCount [in, out]
    *  On input, a number from 1 to WCT_MAX_NODE_COUNT that specifies 
	*  the number of nodes in the wait chain. 
	*  On return, the number of nodes retrieved. 
	*  If the array cannot contain all the nodes of the wait chain, 
	*  the function fails, GetLastError returns ERROR_MORE_DATA, 
	*  and this parameter receives the number of array elements 
	*  required to contain all the nodes.
    *  For asynchronous sessions, check the value that is passed to the callback function. 
	*  Do not free the variable until the callback function has returned.
    * 
	* NodeInfoArray [out]
    *  An array of WAITCHAIN_NODE_INFO structures that receives the wait chain.
    *  For asynchronous sessions, check the value that is passed 
	*  to the callback function. Do not free the array until the callback function has returned.
	* 
	* IsCycle [out]
    *  If the function detects a deadlock, this variable is set to TRUE; 
	*  otherwise, it is set to FALSE.
    *  For asynchronous sessions, check the value 
	*  that is passed to the callback function. 
	*  Do not free the variable until the callback function has returned.
    */
   if (!GetThreadWaitChain(
	      hWCTSession, 
		  NULL, 
		  WCTP_GETINFO_ALL_FLAGS,
          TID, 
		  &dwNodesInChain, 
		  chain, 
		  &bDeadlock)) 
   {
       dwNodeCount = 0;
	   /* Call onThread callback */
       OnThread(TID, FALSE, 0);
       return;
   }

   // Start the chain processing for the current thread
   dwNodeCount = min(dwNodesInChain, WCT_MAX_NODE_COUNT);
   OnThread(TID, bDeadlock, dwNodesInChain);

   // For each node in the chain, call the virtual method with details
   for 
   (
       DWORD current = 0;
       current < min(dwNodesInChain, WCT_MAX_NODE_COUNT);
       current++
   ) 
   {
        OnChainNodeInfo(TID, current, chain[current]);
   }
}
Exemplo n.º 2
0
void PrintWaitChain(__in DWORD ThreadId)
/*++

Routine Description:

    Enumerates all threads (or optionally only threads for one
    process) in the system. It the calls the WCT API on each thread.

Arguments:

    ThreadId--Specifies the thread ID to analyze.

Return Value:

    (none)

--*/
{
    WAITCHAIN_NODE_INFO NodeInfoArray[WCT_MAX_NODE_COUNT];
    DWORD Count, i;
    BOOL IsCycle;

    printf("%d: ", ThreadId);

    Count = WCT_MAX_NODE_COUNT;

    // Make a synchronous WCT call to retrieve the wait chain.
    if (!GetThreadWaitChain(g_WctHandle, NULL, WCTP_GETINFO_ALL_FLAGS, ThreadId, &Count, NodeInfoArray, &IsCycle)) {
        printf("Error (0X%x)\n", GetLastError());
        return;
    }

    // Check if the wait chain is too big for the array we passed in.
    if (Count > WCT_MAX_NODE_COUNT) {
        printf("Found additional nodes %d\n", Count);
        Count = WCT_MAX_NODE_COUNT;
    }

    // Loop over all the nodes returned and print useful information.
    for (i = 0; i < Count; i++) {
        switch (NodeInfoArray[i].ObjectType) {
        case WctThreadType:
            // A thread node contains process and thread ID.
            printf("[%x:%x:%s]->", NodeInfoArray[i].ThreadObject.ProcessId, NodeInfoArray[i].ThreadObject.ThreadId,
                   ((NodeInfoArray[i].ObjectStatus == WctStatusBlocked) ? "b" : "r"));
            break;

        default:
            // A synchronization object.

            // Some objects have names...
            if (NodeInfoArray[i].LockObject.ObjectName[0] != L'\0') {
                printf("[%s:%S]->", STR_OBJECT_TYPE[NodeInfoArray[i].ObjectType - 1].Desc,
                       NodeInfoArray[i].LockObject.ObjectName);
            } else {
                printf("[%s]->", STR_OBJECT_TYPE[NodeInfoArray[i].ObjectType - 1].Desc);
            }
            if (NodeInfoArray[i].ObjectStatus == WctStatusAbandoned) {
                printf("<abandoned>");
            }
            break;
        }
    }

    printf("[End]");

    // Did we find a deadlock?
    if (IsCycle) {
        printf(" !!!Deadlock!!!");
    }

    printf("\n");
}