Paolo Pialorsi

SOA, Workflow Foundation (WF), Windows Communication Foundation (WCF) e le Architetture Distribuite

News

StackTrace, Assembly e .NET

Oggi io e Cristian abbiamo perso quasi un'ora a rincorrere un bug che si presentava in un'applicazione che, compilata in debug funzionava benissimo, mentre in release si schiantava all'avvio. Bello eh?! :-)

Alla fine, dopo aver tribulato per parecchio tempo, abbiamo scoperto una cosa a dir poco singolare. Non voglio parlare di bug, perchè non ne sono ancora sicuro, però di effetto collaterale :-) di qualcosa di strano sì ...

Guardate questo codice (scaricabile per intero da qui):

using System;
using System.Reflection;
using System.Diagnostics;
namespace ClassLibraryTest
{
 public class TestClass
 {
  public String ExecutingAssemblyName(Boolean showProblem)
  {
   if (showProblem)
    return(GetExecutingAssembly(2).FullName);
   else
    return(GetExecutingAssemblyOk(2).FullName);
  }
  private System.Reflection.Assembly GetExecutingAssembly(Int32 stackWalkLevel)
  {
   // Ottengo lo stack
   StackTrace stack = new StackTrace(stackWalkLevel, false);
   // Ottengo il frame
   StackFrame frame = stack.GetFrame(0);
   // Ottengo il nome del metodo
   MethodBase method = frame.GetMethod();
   // Leggo e restituisco l'assembly che contiene il chiamante   
   return(method.DeclaringType.Assembly);
  }
  private System.Reflection.Assembly GetExecutingAssemblyOk(Int32 stackWalkLevel)
  {
   // Ottengo lo stack
   StackTrace stack = new StackTrace(stackWalkLevel, false);
   // Ottengo il frame
   StackFrame frame = stack.GetFrame(0);
   // Ottengo il nome del metodo
   MethodBase method = frame.GetMethod();
   // Leggo e restituisco l'assembly che contiene il chiamante   
   return(Assembly.Load(method.DeclaringType.Assembly.FullName));
  }
 }
}

Provate a chiamare il metodo ExecutingAssemblyName da una classe di un progetto ASP.NET, perchè negli altri casi non succede.
Ora se siete in debug il metodo GetExecutingAssembly funziona correttamente. Se passate in Release, smette di funzionare, in quanto la lettura della proprietà FullName restituisce il fullname di System.Web, anzichè quello corretto.
Lo so sembra assurdo ... per questo allego il progetto. Così potete provare anche voi e dirmi se: 1) succede anche a voi, io ho provato su 2 macchine diverse e succede 2) se vi viene in mente il perchè (Marco?! Hai delle idee in merito?)

La cosa è molto curiosa. Purtroppo FullName ha una implementazione riservata:

[MethodImpl(MethodImplOptions.InternalCall)]
private extern string GetFullName();

come si vede con Reflector. Chissà che succede lì dentro :-) ...

Cambiando l'istruzione:

return(method.DeclaringType.Assembly);

con:

return(Assembly.Load(method.DeclaringType.Assembly.FullName));

che semplicemente ricarica l'assembly, che poi tanto è già in memoria nell'AppDomain corrente, tutto funziona regolarmente. Sono abbastanza propenso a pensare che il problema si in FullName perchè se lo chiamo prima di restituire l'assembly, funziona, viceversa se lo chiamo fuori dal mio metodo GetExecutingAssembly smette di funzionare.

Bello vero?! Un'ora di vita persa per questa ragione :-) !!!

Posted: dic 10 2004, 07.26 by paolo | with 9 comment(s)
Filed under:

Comments

TrackBack said:

# dicembre 10, 2004 8.51

paolo said:

Non risolverà il tuo problema, ma volevo cogliere l'occasione per ringraziarvi, cari amici di DevLeap, mi avete accompagnato durante quest' anno di intenso lavoro, siete forti, non c'è tecnologia che vi spaventa, grazie ancora, e non vogliatemi male se resto anonimo. L'importante è sapere che tanti, come me, vi apprezzano e vi stimano moltissimo.
Un grazie a Paolo e Marco in particolare, siete davvero forti, aspetto con ansia un vostro prossimo libro.
# dicembre 10, 2004 10.33

TrackBack said:

# dicembre 11, 2004 12.58

paolo said:

Uhm... non ho approfondito molto ma sicuramente non è un comportamento corretto al 100% e lo fa anche con .NET 2.0. Chi apre la segnalazione a MS?
Forse potrebbe essere un problema legato al fatto che si manipola lo stack di chiamata ma visto che è facilmente riproducibile lo manderei a Redmond.
# dicembre 12, 2004 12.21

paolo said:

Ho fatto io la segnalazione ... vediamo che cosa ne esce...
# dicembre 12, 2004 1.49

TrackBack said:

# dicembre 12, 2004 9.58

TrackBack said:

# dicembre 12, 2004 10.00

TrackBack said:

# dicembre 12, 2004 11.41

TrackBack said:

# dicembre 19, 2004 7.26