ICorProfilerInfo2::DoStackSnapshot (Método)
Recorre los marcos administrados de la pila para el subproceso especificado y envía información al generador de perfiles mediante una devolución de llamada.
Sintaxis
HRESULT DoStackSnapshot(
[in] ThreadID thread,
[in] StackSnapshotCallback *callback,
[in] ULONG32 infoFlags,
[in] void *clientData,
[in, size_is(contextSize), length_is(contextSize)] BYTE context[],
[in] ULONG32 contextSize);
Parámetros
thread
[in] Id. del subproceso de destino.
Si se pasa null en thread
dará como resultado una instantánea del subproceso actual. Si se pasa un elemento ThreadID
de un subproceso diferente, Common Language Runtime (CLR) suspende ese subproceso, realiza la instantánea y se reanuda.
callback
[in] Puntero a la implementación del método StackSnapshotCallback, al que llama CLR para proporcionar al generador de perfiles información sobre cada marco administrado y cada ejecución de marcos no administrados.
El escritor del generador de perfiles es el encargado de implementar el método StackSnapshotCallback
.
infoFlags
[in] Valor de la enumeración COR_PRF_SNAPSHOT_INFO, que especifica la cantidad de datos que StackSnapshotCallback
va a devolver para cada marco.
clientData
[in] Puntero a los datos de cliente y que se pasa directamente a la función de devolución de llamada de StackSnapshotCallback
.
context
[in] Puntero a una estructura CONTEXT
de Win32, que se usa para inicializar el recorrido de pila. La estructura CONTEXT
de Win32 contiene valores de los registros de CPU y representa el estado de la CPU en un momento determinado en el tiempo.
La inicialización ayuda a CLR a determinar dónde comenzar el recorrido de pila, si la parte superior de la pila es código auxiliar no administrado; de lo contrario, se omite la inicialización. Se debe proporcionar un valor de inicialización para un recorrido asincrónico. Si va a realizar un recorrido sincrónico, no es necesario inicializar.
El parámetro context
solo será válido si se ha pasado la marca COR_PRF_SNAPSHOT_CONTEXT en el parámetro infoFlags
.
contextSize
[in] Tamaño de la estructura CONTEXT
a la que se hace referencia en el parámetro context
.
Comentarios
Si se pasa null en thread
dará como resultado una instantánea del subproceso actual. Las instantáneas solo se pueden tomar de otros subprocesos si el subproceso de destino está suspendido en el momento.
Cuando el generador de perfiles quiere recorrer la pila, llama a DoStackSnapshot
. Antes de que CLR devuelve un valor de esa llamada, llama varias veces a StackSnapshotCallback
, una vez por cada marco administrado (o ejecución de marcos no administrados) en la pila. Cuando se encuentran marcos no administrados, debe guiarlos usted mismo.
El orden en el que se recorre la pila es el opuesto a cómo se han insertado los marcos en la pila: marco de hoja (último insertado) en primer lugar, marco principal (primero insertado) en último lugar.
Para obtener más información sobre cómo programar el generador de perfiles para que recorra pilas administradas, vea Recorrido de la pila del generador de perfiles en .NET Framework 2.0: aspectos básicos y más en profundidad.
Un recorrido de pila puede ser sincrónico o asincrónico, tal como se explica en las secciones siguientes.
Recorrido de pila sincrónico
Un recorrido sincrónico de pila implica recorrer la pila del subproceso actual en respuesta a una devolución de llamada. No requiere inicialización ni suspensión.
Realiza una llamada sincrónica cuando, en respuesta a la llamada que CLR realiza a uno de los métodos ICorProfilerCallback (o ICorProfilerCallback2) del generador de perfiles, llama a DoStackSnapshot
para recorrer la pila del subproceso actual. Esto resulta útil cuando quiere ver el aspecto de la pila en una notificación como ICorProfilerCallback::ObjectAllocated. Simplemente se llama a DoStackSnapshot
desde dentro del método ICorProfilerCallback
lo que hace que pase null en los parámetros context
y thread
.
Recorrido de pila asincrónico
Un recorrido de pila asincrónico implica recorrer la pila de un subproceso diferente, o recorrer la pila del subproceso actual, no como respuesta a una devolución de llamada, sino secuestrando el puntero de instrucción del subproceso actual. Un recorrido asincrónico requiere un valor de inicialización si la parte superior de la pila es código no administrado que no forma parte de una llamada a la plataforma (PInvoke) o COM, sino código auxiliar en el propio CLR. Por ejemplo, el código que realiza la compilación Just-In-Time (JIT) o la recolección de elementos no utilizados es código auxiliar.
Para obtener un valor de inicialización, suspenda directamente el subproceso de destino y recorra su pila usted mismo, hasta que encuentre el marco administrado superior. Una vez suspendido el subproceso de destino, obtenga el contexto de registro actual del subproceso de destino. A continuación, determine si el contexto de registro apunta al código no administrado llamando a ICorProfilerInfo::GetFunctionFromIP; si devuelve un elemento FunctionID
igual a cero, el marco es código no administrado. Ahora, recorra la pila hasta que alcance el primer marco administrado y, después, calcule el contexto de inicialización en función del contexto de registro de ese marco.
Llame a DoStackSnapshot
con el contexto de inicialización para comenzar el recorrido de pila asincrónico. Si no proporciona un valor de inicialización, DoStackSnapshot
puede omitir los marcos administrados en la parte superior de la pila y, por lo tanto, obtendrá un recorrido de pila incompleto. Si proporciona un valor de inicialización, debe apuntar al código generado mediante compilación JIT o el generador nativo de imágenes (Ngen.exe); de lo contrario, DoStackSnapshot
devuelve el código de error, CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX.
Los recorridos asincrónicos de pila pueden provocar fácilmente interbloqueos o infracciones de acceso, a menos que siga estas instrucciones:
Cuando suspenda directamente los subprocesos, recuerde que solo un subproceso que nunca ha ejecutado código administrado puede suspender otro subproceso.
Bloquee siempre la devolución de llamada de ICorProfilerCallback::ThreadDestroyed hasta que se complete el recorrido de pila de ese subproceso.
No mantenga un bloqueo mientras el generador de perfiles llame a una función CLR que pueda desencadenar una recolección de elementos no utilizados. Es decir, no mantenga un bloqueo si el subproceso que posee puede realizar una llamada que desencadene una recolección de elementos no utilizados.
También existe riesgo de interbloqueo si llama a DoStackSnapshot
desde un subproceso que el generador de perfiles ha creado para que pueda recorrer la pila de un subproceso de destino independiente. La primera vez que el subproceso que ha creado escribe determinados métodos ICorProfilerInfo*
(incluido DoStackSnapshot
), CLR realizará la inicialización específica de CLR por subproceso en ese subproceso. Si el generador de perfiles ha suspendido el subproceso de destino cuya pila está intentando recorrer y si ese subproceso de destino posee un bloqueo necesario para realizar esta inicialización por subproceso, se producirá un interbloqueo. Para evitar este interbloqueo, realice una llamada inicial a DoStackSnapshot
desde el subproceso creado por el generador de perfiles para recorrer un subproceso de destino independiente, pero no suspenda primero el subproceso de destino. Esta llamada inicial garantiza que la inicialización por subproceso se pueda completar sin interbloqueo. Si DoStackSnapshot
se realiza correctamente e informa al menos de un marco, después de ese punto, será seguro que ese subproceso creado por el generador de perfiles suspenda cualquier subproceso de destino y llame a DoStackSnapshot
para recorrer la pila de ese subproceso de destino.
Requisitos
Plataformas: Vea Requisitos de sistema.
Encabezado: CorProf.idl, CorProf.h
Biblioteca: CorGuids.lib
Versiones de .NET Framework: disponible a partir de la versión 2.0