<?xml version="1.0" encoding="iso-8859-15"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Il lato oscuro - Il blog di Alessandro Catorcini</title><link>http://blogs.aspitalia.com/ale/</link><description>Il lato oscuro - Il blog di Alessandro Catorcini</description><dc:language>it-it</dc:language><managingEditor>noreply(at)aspitalia.com(Il lato oscuro - Il blog di Alessandro Catorcini)</managingEditor><webMaster>daniele(at)aspitalia.com(Daniele Bochicchio)</webMaster><copyright>1998-2008 ASPItalia.com/Il lato oscuro - Il blog di Alessandro Catorcini</copyright><generator>Generated by feed.ASPItalia.com 'Weyoh' 4.8.703</generator><sy:updatePeriod>hourly</sy:updatePeriod><sy:updateFrequency>1</sy:updateFrequency><sy:updateBase>1998-01-01T12:00+00:00</sy:updateBase><image><title>Il lato oscuro - Il blog di Alessandro Catorcini</title><url>http://blogs.aspitalia.com/blogs.gif</url><link>http://blogs.aspitalia.com/ale/</link></image><item><title>Autopsia di un'applicazione - Terza puntata: l'applicazione che si congela</title><link>http://blogs.aspitalia.com/ale/post2265/Autopsia-Applicazione-Terza-Puntata-Applicazione-Congela.aspx</link><pubDate>Tue, 08 Apr 2008 07:08:00 +0100</pubDate><description>&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2265' border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;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: &lt;/p&gt;&lt;ol&gt;&lt;li&gt;un loop infinito&lt;/li&gt;&lt;li&gt;un deadlock&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;Se la fattucchiera non è disponibile, si possono usare altri tool più pratici nell'arsenale del managed developer.&lt;/p&gt;&lt;p&gt;Deadlock: cos'è? &lt;/p&gt;&lt;p&gt;Per avere un deadlock una serie di condizioni deve essere verificata allo stesso tempo: &lt;/p&gt;&lt;ol&gt;&lt;li&gt;il processo ha più di un thread&lt;/li&gt;&lt;li&gt;tutti i thread possono accedere a tutte le risorse&lt;/li&gt;&lt;li&gt;le risorse possono essere acquisite da un solo thread alla volta&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;Anche se la condizione teorica sembra complessa, i deadlock capitano più spesso di quanto sembri. Guardiamo con attenzione le condizioni:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;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. &lt;/li&gt;&lt;li&gt;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)&lt;/li&gt;&lt;li&gt;Molte risorse non sono intrinsecamente condivisibili (per esempio un file in scrittura)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;Il tool e l'eccellente articolo che lo accompagnano si possono scaricare seguendo &lt;a href="http://msdn2.microsoft.com/en-us/magazine/cc163618.aspx"&gt;&lt;font color="#669966"&gt;questo link per l'articolo&lt;/font&gt;&lt;/a&gt; e &lt;a href="http://msdn2.microsoft.com/en-us/magazine/cc164594.aspx"&gt;&lt;font color="#669966"&gt;questo per il codice&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_2.0/" rel="tag"&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Alessandro Catorcini</dc:creator><category>Diagnostica, .NET Framework, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5</category><guid isPermaLink="true">http://blogs.aspitalia.com/ale/post2265/Autopsia-Applicazione-Terza-Puntata-Applicazione-Congela.aspx</guid><slash:comments>1</slash:comments><wfw:comments>http://blogs.aspitalia.com/ale/post2265/Autopsia-Applicazione-Terza-Puntata-Applicazione-Congela.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ale/CommentRSS2265.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2265</trackback:ping></item><item><title>Autopsia di un'applicazione - seconda puntata gli MDA (Managed Debug Assistants)</title><link>http://blogs.aspitalia.com/ale/post2264/Autopsia-Applicazione-Puntata-MDA-Managed-Debug-Assistants.aspx</link><pubDate>Sun, 06 Apr 2008 00:43:00 +0100</pubDate><description>&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2264' border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;A partire dal .NET Framework 2.0, abbiamo introdotto un nuovo strumento per il debugging dei problemi tradizionalmente difficili da diagnosticare.&lt;/p&gt;&lt;p&gt;I cosiddetti MDA (Managed Debugging Assistants) consentono di trattare alcune condizioni come eccezioni così da dare l'opportunità di attaccare un debugger.&lt;/p&gt;&lt;p&gt;Per avere la lista completa degli MDA fate riferimento a questa pagina su MSDN: &lt;a href="http://msdn2.microsoft.com/en-us/library/d21c150d.aspx"&gt;&lt;font color="#669966"&gt;Diagnosing Errors with the Managed Debugging Assistants&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Giusto per dare un'aneddoto che mostra la potenza degli MDA, concentriamo l'attenzione su &lt;a href="http://msdn2.microsoft.com/en-us/library/ms228991.aspx"&gt;&lt;font color="#669966"&gt;invalidOverlappedToPInvoke&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;Nel 2005, quando le date per il release to manifacturing (RTM) di Visual Studio 2005 e SQL Server 2005 stavano avvicinandosi rapidamente, eravamo alla dispearata ricerca delle cause di un numero anomalo di NT Heap corruptions che lo stress testing stava trovando. Dopo uno stillicidio di due mesi, decidemmo di dedicare l'intero reliability team di entrambi i prodotti a scovare il colpevole. Dopo quattro settimane di immersione full time in memory dump e stack traces, la causa fu trovata in un'innocente funzione che faceva I/O sulla rete attraverso un I/O completion port.&lt;/p&gt;&lt;p&gt;Questo meccanismo dell'OS consente di trasferire il controllo dell'operazione ad un kernel thread e gestisce il messaging con l'applicazione chiamante. I dati sono scambiati attraverso una struct OVERLAPPED allocata dal caller in user mode e scritta dal kernel thread.&lt;/p&gt;&lt;p&gt;Il codice che aveva causato il patatrac non aveva fatto nulla di terribile, ed era formalmente corretto (motivo per cui non lo avevamo trovato immediatamente). L'unico problema era che la struttura OVERLAPPED era allocata sulla GC heap e non era pinned. Questo faceva sì che in certi casi la struttura venisse processata dal garbage collector prima che l'operazione di I/O potesse finire. Quando questo succedeva, il kernel thread scriveva sull'NT Heap handle che gli era stata passata, ma questa memoria era nel migliore dei casi free memory nel GC Heap o qualche altro oggetto (da cui le corruption).&lt;/p&gt;&lt;p&gt;Dopo questa avventura, introducemmo questo MDA, che genera un'eccezione a runtime ogni volta che una struttura OVERLAPPED allocata tramite P/Invoke è passata ad un kernel thread ed è raccolta dal garbage collector prima del tempo.&lt;/p&gt;&lt;p&gt;Per cui, se la vostra applicazione vi sta facendo impazzire e le avete provate tutte, forse un semplice&lt;/p&gt;&lt;p&gt;&lt;code&gt; Windows Registry Editor Version 5.00 &lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework] &amp;quot;MDA&amp;quot;=&amp;quot;1&amp;quot; &lt;/code&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;Può essere utile.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;A presto&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;--Alessandro&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework_2.0/" rel="tag"&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Alessandro Catorcini</dc:creator><category>Diagnostica, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Framework</category><guid isPermaLink="true">http://blogs.aspitalia.com/ale/post2264/Autopsia-Applicazione-Puntata-MDA-Managed-Debug-Assistants.aspx</guid><slash:comments>2</slash:comments><wfw:comments>http://blogs.aspitalia.com/ale/post2264/Autopsia-Applicazione-Puntata-MDA-Managed-Debug-Assistants.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ale/CommentRSS2264.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2264</trackback:ping></item><item><title>Autopsia di un'applicazione - prima puntata</title><link>http://blogs.aspitalia.com/ale/post2247/Autopsia-Applicazione-Puntata.aspx</link><pubDate>Thu, 06 Mar 2008 07:14:00 +0100</pubDate><description>&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2247' border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Vorrei spendere qualche tempo per parlare di diverse tecniche di diagnosi di un'applicazione. In questa serie di post cominceremo ad analizzare le ragioni per le quali un'applicazione scritta usando il .NET Framework si pianta, presenterò alcuni esempi e pattern che possono causare quei comportamenti e mostrerò alcune tecniche diagnostiche per risalire alle cause prime di problemi profondi (interop signature mismatch e data corruption) molto difficili da diagnosticare con i tool usati comumente.&lt;/p&gt;&lt;p&gt;La prima puntata è una chiaccherata sulle ragioni di morte di un processo che contiene in CLR.&lt;/p&gt;&lt;p&gt;Qualche anno fa, quando si scriveva in C o C++ era facile piantare un programma. Bastava dimenticarsi di assegnare a null un puntatore assegnato a qualcosa che era stato deallocato e il tuo programma si piantava nel modo più creativo. Oggi è molto più difficile trovarsi un una situazione dove un'applicazione scritta nei Framework del XXI secolo sia così fragile.&lt;/p&gt;&lt;p&gt;Quando un'applicazione scritta usando il .NET Framework si pianta, succede uno dei seguenti eventi ritenuti catastrofici dal runtime (in ordine di probabilità):&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Un'eccezione sollevata nel codice non è stata gestita &lt;/li&gt;&lt;li&gt;Si è verificata una access violation nell'interop (cioè sei andato a leggere memoria che non è tua) &lt;ol&gt;&lt;li&gt;causata dal codice nativo eseguito &lt;/li&gt;&lt;li&gt;causata da un errore nel codice di marshalling (signature sbagliata, convenzioni di allocazione non rispettate tra caller e callee, etc.) &lt;/li&gt;&lt;li&gt;heap corruption causata da codice nativo &lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;Una risorsa critica per l'esecuzione del programma non è disponibile. Quando questo succede, spesso il programma ha un leak di risorse native (le alloca e non le rilascia mai) o un cattivo uso del Dispose Pattern che lo portano ad una morte prematura per soffocamento. Le risorse la mancanza delle quali può uccidere il processo sono &lt;ol&gt;&lt;li&gt;Memoria &lt;/li&gt;&lt;li&gt;System Handles &lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;Stack overflow (raro - può succedere se si esagera con la profondità di una query o di una ricorsione) &lt;/li&gt;&lt;li&gt;Un bug nel CLR che causa una access violation (se ne trovate uno dopo il CLR V2 vi pago da bere :-) ) &lt;/li&gt;&lt;/ol&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;La domanda fondamentale è &amp;quot;Perché un processo viene distrutto in questi casi&amp;quot;.&lt;/p&gt;&lt;p&gt;La risposta è di una semplicità disarmante:&amp;quot;Perché è l'unica azione che garantisce la correttezza dell'elaborazione e il più possibile l'integrità dei dati&amp;quot;. Se si continua l'esecuzione in questi stati, è garantito che alcuni degli invarianti che il programmatore ha posto come ipotesi per il funzionamento dell'applicazione sono stati violati.&lt;/p&gt;&lt;p&gt;In questo caso sia per ragioni di correttezza sia di sicurezza, il comportamento più sicuro per l'applicazione è terminare il processo e generare un dump utile per scoprire cosa è andato storto.&lt;/p&gt;&lt;p&gt;Questa considerazione è la ragione dietro alla decisione di cambiare il comportamento di default del runtime in caso di una eccezione non gestita. Mentre .NET 1.1 consente di proseguire, .NET 2.0 e superiori termina il processo a meno che non si setti un parametro di configurazione esplicitamente.&lt;/p&gt;&lt;p&gt;&amp;lt;configuration&amp;gt; &lt;br /&gt;  &amp;lt;runtime&amp;gt;&lt;br /&gt;     &amp;lt;legacyUnhandledExceptionPolicy enabled=&amp;quot;true&amp;quot; /&amp;gt; &lt;br /&gt;  &amp;lt;/runtime&amp;gt; &lt;br /&gt; &amp;lt;/configuration&amp;gt;&lt;/p&gt;&lt;p&gt;La prossima volta parleremo di MDA (Managed Debugging Assistants) uno strumento potente e poco conosciuto per la diagnostica di problemi seri e difficili da identificare altrimenti.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_2.0/" rel="tag"&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Pattern/" rel="tag"&gt;Pattern&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Alessandro Catorcini</dc:creator><category>Diagnostica, .NET Framework, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, Pattern</category><guid isPermaLink="true">http://blogs.aspitalia.com/ale/post2247/Autopsia-Applicazione-Puntata.aspx</guid><slash:comments>3</slash:comments><wfw:comments>http://blogs.aspitalia.com/ale/post2247/Autopsia-Applicazione-Puntata.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ale/CommentRSS2247.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2247</trackback:ping></item></channel></rss>