2010-11-22 6 views
4

J'ai un site qui fonctionne dans ASP.NET 3.5, NHibernate 2.2 et Sprint .NET pour l'injection de dépendance. Sur notre serveur de test, une erreur plutôt étrange se produit, et presque chaque fois qu'il y a plusieurs utilisateurs en ligne. Une fois le problème résolu, cette erreur s'affiche pour chaque utilisateur et chaque requête effectuée, jusqu'à ce que vous définissiez un IISRESET. Alors tout est ok.Erreur étrange: [ArgumentOutOfRangeException: 'count' doit être non-négatif

est ici l'exception:

'count' must be non-negative. 
Parameter name: count 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ArgumentOutOfRangeException: 'count' must be non-negative. 
Parameter name: count 

Source Error: 
[No relevant source lines] 

Source File: c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET  Files\root\4bf9aa39\6dcf5fc6\App_Web_z9ifuy6t.6.cs Line: 0 

Stack Trace: 
[ArgumentOutOfRangeException: 'count' must be non-negative. 
Parameter name: count] 
System.String.CtorCharCount(Char c, Int32 count) +10082288 
Spring.Objects.Factory.Support.AbstractObjectFactory.GetObjectInternal(String name, Type requiredType, Object[] arguments, Boolean suppressConfigure) +3612 
Spring.Objects.Factory.Support.AbstractObjectFactory.GetObject(String name) +75 
Spring.Objects.Factory.Support.DefaultListableObjectFactory.GetObjectsOfType(Type type, Boolean includePrototypes, Boolean includeFactoryObjects) +365 
Spring.Context.Support.AbstractApplicationContext.GetObjectsOfType(Type type, Boolean includePrototypes, Boolean includeFactoryObjects) +136 
Spring.Context.Support.AbstractApplicationContext.GetObjectsOfType(Type type) +66 


[ActivationException: Activation error occured while trying to get instance of type InfoTextService, key ""] 
    Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in  c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:57 
Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance() in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:90 
OurProjectsNamespace.Infrastructure.ObjectLocator.LocateService() +86 

Répondre

3

C'est en effet une erreur très bizarre. Quand vous regardez la source du AbstractObjectFactory.GetObjectInternal vous verrez la structure suivante:

[ThreadStatic] 
private int nestingCount; 

protected object GetObjectInternal(...) 
{ 
    const int INDENT = 3; 
    bool hasErrors = false; 
    try 
    { 
     nestingCount++; 

     if (log.IsDebugEnabled) 
     { 
      log.Debug("msg" + 
       new String(' ', nestingCount * INDENT)); 
     } 

     // More code: Calls self recursively. 
    } 
    catch 
    { 
     nestingCount--; 
     hasErrors = true; 

     if (log.IsErrorEnabled) 
     { 
      log.Error("msg" + 
       new String(' ', nestingCount * INDENT)); 
     }   
    } 
    finally 
    { 
     if (!hasErrors) 
     { 
      nestingCount--; 
      if (log.IsDebugEnabled) 
      { 
       log.Debug("msg" + 
        new String(' ', nestingCount * INDENT)); 
      }   
     } 
    } 
} 

L'exception que vous voyez doit être jeté par l'un des trois appels new String(' ', nestingCount * INDENT). Cet appel constructeur string particulier se déclenche lorsque la valeur fournie est négative. Parce que INDENT est un const, nestingCount doit avoir une valeur négative dans ce cas. nestingCount est une variable statique de thread. Les variables thread-static sont toujours initialisées avec leur valeur par défaut (0 dans ce cas) et ne peuvent pas être influencées par d'autres threads. De plus, nestingCount n'est jamais utilisé en dehors de cette méthode. Étant donné que nestingCount est thread-static et seulement utilisé dans cette méthode, il est difficile d'imaginer un scénario nestingCount peut devenir négatif. Peut-être dans le cas d'une exception asynchrone (ThreadAbort), mais même cela je trouve difficile à imaginer. L'autre option est que la variable thread-static est modifiée par quelqu'un d'autre en utilisant la réflexion.

Mais la grande question est: comment résoudre ce problème?

Solution:

Il n'y a qu'une seule chose que je peux penser et qui est reconfigure log4net d'une manière qui déboguer informations ne sont pas enregistrées. En refusant les informations de débogage, le constructeur string(char, int) ne sera probablement plus jamais appelé, ce qui cachera le problème. Pas très joli, mais peut-être efficace. Cela pourrait fonctionner, car les journaux AbstractObjectFactory en utilisant la variable log qui est initialisé comme suit:

this.log = LogManager.GetLogger(this.GetType()); 

Vous pouvez le faire en désactivant globalement l'écriture des informations de débogage dans log4net, ou -Lorsque vous pensez que cela est overkill- par configuration de log4net pour désactiver les informations de débogage pour le type Spring.Objects.Factory.Support.DefaultListableObjectFactory (l'instance qui provoque réellement l'exception).

Bonne chance.

+0

La désactivation du débogage pour Spring.Objects.Factory.Support.DefaultListableObjectFactory est une idée qui pourrait fonctionner. Je vais essayer ceci et voir que l'erreur ne se produira plus. L'erreur est définitivement bizarre mais très intéressante. Espérons que la cause de base sera limitée à cette erreur ... Merci Steven! Je garderai le poste mis à jour si quelque chose de nouveau arrive. – Mattias

+0

@Mattias: Je suis très curieux de savoir si mes observations étaient correctes et si la désactivation du débogage a effectivement résolu votre problème. – Steven

+0

J'espère pouvoir vous répondre rapidement. Cela n'arrive que sur le serveur de production qui n'est pas encore en ligne. Donc, après la prochaine mise à jour, nous verrons. – Mattias

0

J'ai vu cette erreur se produit lorsqu'une colonne de base de données est mis en correspondance avec plus d'une propriété. Un cas typique est quand une colonne de clé étrangère est mappée à une propriété et à la collection. Une deuxième ou une troisième paire d'yeux sur les fichiers de configuration permet de les repérer.

Une torsion avec ceci est que cela se produit pour tous les utilisateurs. Avez-vous un objet persistant qui est stocké dans l'état de l'application?

+0

Je ne peux pas publier tout le code en raison de la confidentialité, mais l'objet qui se trouve est un objet interne avec un ISession et un exceptionExceptionHandler comme arguments de constructeur. L'erreur apparaît lorsque cet objet est en cours d'initialisation. – Mattias

0

Dans mon cas, cette erreur s'est produite après un certain temps au cours des tests de performance. Cela commence bien et après quelque temps cette erreur apparaît.

Il s'avère qu'il a été causé par une variable [ThreadLocal] totalement indépendante que j'ai utilisée dans mon code. Je l'ai remplacé par un paramètre de méthode et maintenant cela fonctionne bien.