Metodo ICorProfilerInfo2::DoStackSnapshot
Verifica i frame gestiti sullo stack per il thread specificato e invia le informazioni al profiler tramite un callback.
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);
Parametri
thread
[in] ID del thread di destinazione.Quando si passa null nel thread, viene generato uno snapshot del thread corrente. Se viene passata una proprietà ThreadID di un thread diverso, Common Language Runtime sospenderà il thread, genererà lo snapshot e riprenderà l'esecuzione.
callback
[in] Puntatore all'implementazione del metodo StackSnapshotCallback, che viene chiamato da CLR per fornire al profiler le informazioni su ciascun frame gestito e su ciascuna esecuzione di frame non gestiti.Il metodo StackSnapshotCallback viene implementato dal writer del profiler.
infoFlags
[in] Valore dell'enumerazione COR_PRF_SNAPSHOT_INFO che specifica la quantità di dati che StackSnapshotCallback deve restituire per ogni frame.clientData
[in] Puntatore ai dati client, passati direttamente alla funzione di callback StackSnapshotCallback.context
[in] Puntatore a una struttura CONTEXT Win32 utilizzata per effettuare il seeding del percorso chiamate nello stack. La struttura CONTEXT Win32 contiene i valori dei registri della CPU e rappresenta lo stato di quest'ultima in un determinato momento.Il valore di inizializzazione è utile a Common Language Runtime per determinare dove iniziare la verifica del percorso chiamate nello stack, se la cima dello stack è codice di supporto non gestito. In caso contrario, il valore di inizializzazione viene ignorato. È necessario fornire un valore di inizializzazione per una verifica asincrona. Se si sta eseguendo una verifica sincrona, non è necessario alcun valore di inizializzazione.
Il parametro context è valido solo se il flag COR_PRF_SNAPSHOT_CONTEXT è stato passato nel parametro infoFlags.
contextSize
[in] Dimensione della struttura CONTEXT, a cui fa riferimento il parametro context.
Note
Quando si passa null per thread, viene generato uno snapshot del thread corrente. Gli snapshot possono essere creati da altri thread solo se il thread di destinazione al momento è sospeso.
Quando il profiler desidera verificare il percorso chiamate nello stack, chiama DoStackSnapshot. Prima che Common Language Runtime esca da tale chiamata, chiama StackSnapshotCallback più volte, una per ogni frame gestito (o esecuzione di frame non gestiti) sullo stack. Quando vengono rilevati frame non gestiti, è necessario verificarli manualmente.
L'ordine in cui viene eseguita la verifica del percorso chiamate nello stack è l'inverso dell'ordine in cui i frame sono stati inseriti nello stack: prima il frame foglia (inserito per ultimo) e alla fine il frame principale (inserito per primo).
Per ulteriori informazioni su come programmare il profiler per verificare il percorso chiamate gestite nello stack, vedere Profiler Stack Walking in the .NET Framework 2.0: Basics and Beyond (informazioni in lingua inglese) in MSDN Library.
Un percorso chiamate nello stack può essere sincrono o asincrono, come spiegato nelle sezioni seguenti.
Verifica sincrona del percorso chiamate nello stack
Una verifica sincrona del percorso chiamate nello stack comporta la verifica dello stack del thread corrente in risposta a un callback. Non è necessario effettuare seeding o sospensioni.
Si effettua una chiamata sincrona quando, in risposta alla chiamata a uno dei metodi ICorProfilerCallback (o ICorProfilerCallback2) del profiler da parte di Common Language Runtime, viene chiamato DoStackSnapshot per verificare il percorso chiamate nello stack del thread corrente. Tale operazione è utile quando si desidera visualizzare l'aspetto dello stack in una notifica quale ICorProfilerCallback::ObjectAllocated. È sufficiente chiamare DoStackSnapshot dall'interno del metodo ICorProfilerCallback method, passando null nei parametri context e thread.
Verifica asincrona del percorso chiamate nello stack
Una verifica asincrona del percorso chiamate nello stack comporta la verifica dello stack di un thread diverso o la verifica dello stack del thread corrente, non in risposta a un callback, ma assumendo il controllo del puntatore all'istruzione del thread corrente. Una verifica asincrona richiede un valore di inizializzazione se la cima dello stack è codice non gestito che non fa parte di un PInvoke o di una chiamata COM, ma codice di supporto in Common Language Runtime. Ad esempio, il codice per la compilazione JIT (Just-In-Time) o la Garbage Collection è codice di supporto.
Si ottiene un valore di inizializzazione sospendendo direttamente il thread di destinazione e verificando manualmente il percorso chiamate nel relativo stack fino a trovare il frame gestito di livello più alto. Dopo che il thread di destinazione è stato sospeso, ottenerne il contesto del registro corrente. Successivamente, determinare se il contesto del registro punta a codice non gestito chiamando ICorProfilerInfo::GetFunctionFromIP. Se restituisce un valore FunctionID uguale a zero, il frame è codice non gestito. A questo punto, verificare il percorso chiamate nello stack fino ad arrivare al primo frame gestito e quindi calcolare il contesto del valore di inizializzazione in base al contesto del registro per il frame.
Chiamare DoStackSnapshot con il contesto del valore di inizializzazione per avviare la verifica asincrona del percorso chiamate nello stack. Se non si specifica un valore di inizializzazione, DoStackSnapshot potrebbe ignorare i frame gestiti in cima allo stack e, di conseguenza, fornire una verifica incompleta del percorso chiamate nello stack. Se si specifica un valore di inizializzazione, deve puntare a codice compilato tramite JIT o prodotto dal generatore di immagini native (Ngen.exe). In caso contrario, DoStackSnapshot restituisce il codice di errore CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX.
Le verifiche asincrone del percorso chiamate nello stack possono facilmente dare luogo a deadlock o a violazioni dell'accesso se non ci si attiene alle seguenti linee guida:
Quando si sospendono direttamente i thread, ricordare che solo un thread che non ha mai eseguito codice gestito può sospendere un altro thread.
Bloccarsi sempre nel callback di ICorProfilerCallback::ThreadDestroyed fino al completamento della verifica del percorso chiamate nello stack del thread in questione.
Non mantenere un blocco mentre il profiler chiama una funzione CLR che può avviare una Garbage Collection. In altri termini, non mantenere un blocco se il thread proprietario può effettuare una chiamata che dà luogo a una Garbage Collection.
Esiste inoltre un rischio di deadlock se si chiama DoStackSnapshot da un thread creato dal profiler affinché sia possibile verificare il percorso chiamate nello stack di un thread di destinazione separato. La prima volta che il thread creato immette determinati metodi ICorProfilerInfo* (incluso DoStackSnapshot), CLR eseguirà l'inizializzazione per thread, specifica per CLR in tale thread. Se il profiler ha sospeso il thread di destinazione di cui si sta tentando di analizzare lo stack e se il thread di destinazione ha un blocco necessario per l'esecuzione dell'inizializzazione per thread, si verificherà un deadlock. Per evitare questo deadlock, effettuare una chiamata iniziale in DoStackSnapshot dal thread creato dal profiler per analizzare un thread di destinazione separato, ma non sospendere prima il thread di destinazione. Questa chiamata iniziale garantisce che l'inizializzazione per thread possa essere completata senza deadlock. Se DoStackSnapshot viene eseguito e segnala almeno un fotogramma, dopo quel punto per motivi di sicurezza il thread creato dal profiler dovrà sospendere i thread di destinazione e chiamare DoStackSnapshot per verificare il percorso chiamate nello stack di un thread di destinazione.
Requisiti
Piattaforme: vedere Requisiti di sistema di .NET Framework.
Intestazione: CorProf.idl, CorProf.h
Libreria: CorGuids.lib
Versioni di .NET Framework: 4, 3.5 SP1, 3.5, 3.0 SP1, 3.0, 2.0 SP1, 2.0