Autopsia di un'applicazione - Terza puntata: l'applicazione che si congela

di Alessandro Catorcini, in Diagnostica,

Se diagnosticare perché un'applicazione si pianta non è sempre facile, diagnosticare perché un'applicazione si congela o va in un loop infinito non lo è praticamente mai. Ci sono due ragioni fondamentali per un application hang:

  1. un loop infinito
  2. un deadlock

mentre individuare il primo è relativamente semplice se avviene nel vostro codice - basta attaccare un debugger, fare un break e leggere lo stack-trace, individuare un deadlock di solito richiede riti voodoo e interventi del mago di fiducia.

Se la fattucchiera non è disponibile, si possono usare altri tool più pratici nell'arsenale del managed developer.

Deadlock: cos'è?

Per avere un deadlock una serie di condizioni deve essere verificata allo stesso tempo:

  1. il processo ha più di un thread
  2. tutti i thread possono accedere a tutte le risorse
  3. le risorse possono essere acquisite da un solo thread alla volta

Il deadlock avviene quando un thread A prende possesso della risorsa 1 (per esempio un socket handle di rete), mentre il thread B prende possesso della risorsa 2 (per esempio un handle di file); se a questo punto il thread A cerca di acquisire la risorsa 2 e il thread B cerca di acquisire la risorsa 1, entrambi i thread si sospenderanno in eterno aspettandosi l'un l'altro.

Anche se la condizione teorica sembra complessa, i deadlock capitano più spesso di quanto sembri. Guardiamo con attenzione le condizioni:

  1. un processo ha più di un thread. Anche se sembra una cosa banale, ogni applicazione scritta con .NET ne ha almeno tre: l'execution thread, il GC thread e il finalizer thread. Se poi si usano timer, c'è anche un timer thread.
  2. tutti i thread possono accedere a tutte le risorse. Questa condizione è vera a meno che non sia applicata una policy nel codice del processo (con eccezioni, come l'STA thread per la UI e la message pump)
  3. Molte risorse non sono intrinsecamente condivisibili (per esempio un file in scrittura)

Se sospetti che la tua applicazione stia esibendo un comportamento compatibile con un deadlock, puoi provare ad usare un tool che Joe Duffy ha scritto usando le hosting API del CLR.

Uno dei comportamenti che possono essere personalizzati tramite queste API è che l'host nativo del CLR può essere notificato ogni volta che un thread è creato, distrutto, sospeso o messo in condizione di essere eseguito. Questo tool, crea un log dei thread presenti nel processo ed esegue un algoritmo di deadlock detection ad ogni cambiamento di stato. Se un deadlock viene identificato, l'host solleva un'eccezione critica che può essere catturata se il processo girava con un debugger attaccato. In questo modo si viene allertati nel momento in cui avviene la presa del lock che genera il deadlock e si può intervenire sul codice.

Il tool e l'eccellente articolo che lo accompagnano si possono scaricare seguendo questo link per l'articolo e questo per il codice

I lettori attenti avranno notato che ho glissato elegantemente sul caso dei loop infiniti nel codice non vostro. Questo è il problema peggiore e sarà oggetto di un post futuro.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese