web-dev-qa-db-fra.com

Pourquoi mon pool d'applications IIS7 s'arrête-t-il après une exception dans un DLL appelé à partir d'une page ASP.NET?

J'ai lu les articles problème d'arrêt du pool d'applications ASP.NET et IIS 7.5: problème avec le pool d'applications mais ils n'ont pas répondu à ma question.

J'ai une page C # ASP.NET qui instancie en code-behind une classe à partir d'un DLL fourni via le répertoire BIN, puis appelle une méthode sur cette instance. La méthode à l'intérieur de DLL renvoie System.ArgumentException En raison d'une colonne inexistante dans un objet DataRow. Le journal des événements affiche l'erreur suivante:

Source: ASP.NET 2.0.50727.0
Application ID: /LM/W3SVC/1/ROOT/...
Process ID: 9476
Exception: System.ArgumentException
Message: Column 'someColumn' does not belong to table.
StrackTrace: 

Le code appelant dans la page ASP.NET encapsule l'appel de méthode dans un bloc générique try-catch. Lorsque je demande la page, cela bloque le pool d'applications correspondant de mon instance IIS et mon site Web n'est plus disponible (erreur 503). Je dois redémarrer manuellement le pool d'applications et le site fonctionne à nouveau.

Mise à jour Comme demandé, le bloc try catch Du code ASP.NET derrière:

try
{
    SomeExternalClass someExternalClass = new SomeExternalClass();
    someExternalClass.SomeMethod( someId );
}
catch( Exception ex )
{
    // "smp" is an instance of "StatusMessagePanel", a control we use on all pages 
    // to show error information, basically a div container with an icon.
    smp.ShowError( ex.Message ); 
}

Maintenant, ma question est de savoir pourquoi une exception relativement "simple" telle que le System.ArgumentException Levée lorsque vous essayez d'accéder à une colonne DataRow non existante, bloque tout le site Web? Le bloc générique try-catch De la page ASP.NET n'aide pas non plus, et cela ne devrait pas être la raison pour rendre complètement l'ensemble du site Web indisponible, ou est-ce une hypothèse erronée? Je n'aurais jamais pensé que cela pouvait essentiellement faire tomber le serveur (II).

En prévision de personnes me disant que je devrais vérifier l'existence de la colonne avant d'y accéder: je le sais et le code hérité a maintenant été changé, mais ce n'est pas ma question comme décrit ci-dessus, je voudrais savoir pourquoi le les conséquences sont si dramatiques.

Mise à jour 2

La méthode en question étant appelée dans le DLL démarre un thread qui est encapsulé dans un bloc try-catch:

[...]
try
{
    ThreadStart starter = () => CreateReport(...)
    Thread thread = new Thread( starter );
    thread.Start();
    if( !thread.Join( TimeSpan.FromMinutes( 15 ) ) )
    {
        // Log some timeout warning
    }
    else
    {
        // Log information about successful report generation
    }
}
catch( Exception ex )
{
    // Log error information
}
23
Gorgsenegger

Votre pool d'applications est très probablement arrêté automatiquement par la fonctionnalité Rapid Fail Protection IIS , comme vous le notez dans les questions liées. Si vous consultez votre journal des événements, plusieurs exceptions non gérées peuvent être levées en succession rapide.

Autrement dit, suffisamment d'exceptions non gérées dans un intervalle de temps configurable (la valeur par défaut est 5 en 5 minutes) arrêtera l'AppPool, provoquant la réponse 503 Service Unavailable.

Le raisonnement derrière cette fonctionnalité est que si vous avez une application défectueuse, vous ne voulez probablement pas qu'elle soit redémarrée automatiquement à chaque demande ultérieure, consommant des ressources et éventuellement corrompant des données.

Je dois admettre que ce n'est pas le comportement "par défaut" auquel je m'attendais non plus.

Découvrez explication de Rick Stahls , c'est un peu plus en profondeur.

Pour vraiment résoudre ce problème, vous devez intercepter l'exception ou empêcher que l'exception ne soit levée (comme le suggère @leppie). Les exceptions non gérées sont censées détruire tout le processus d'exécution (ce qui signifie que le processus de demande/de travail unique, pas IIS) - cela rend le code .Net beaucoup plus facile à déboguer, car il ne masque pas les erreurs ou ne bloque simplement l'application.

Notez que cela a été modifié dans .Net 2.0:
http://msdn.Microsoft.com/en-us/library/ms228965.aspx
http://support.Microsoft.com/kb/911816

Mise à jour
Sur la base de votre mise à jour ci-dessus, je ne pense pas que votre exception soit réellement interceptée, si elle est levée à partir de CreateReport(). Cette méthode s'exécute sur un thread séparé:

exception still thrown

Vous avez besoin d'un try-catch dans le corps de CreateReport() s'il n'y en a pas déjà un:

public static void CreateReport() {
    try {
        throw new Exception("reducto");
    } catch {
        Console.WriteLine("done did.");
    }
}
19
Zachary Yates

Cela m'est arrivé une fois. La vraie erreur (dans mon cas) était un débordement de pile qui fermait la piscine.

Il semble que IIS se protégeait contre la consommation de trop de ressources.

J'ai trouvé le problème en utilisant DebugDiag.

Voici où j'ai commencé: http://www.webdebug.net/index.php/2012/12/collect-iis-crash-dump-with-debugdiag/

Je voudrais comprendre pourquoi une exception dans un DLL externe peut entraîner l'arrêt du pool d'applications IIS, même si l'exception est interceptée dans le = DLL et également lors de l'appel de la méthode de la DLL à partir du code derrière la page ASP.NET.

La DLL externe s'exécute également dans votre pool d'applications. Un plantage majeur de cette dll provoquera également le plantage de votre pool d'applications. Certaines exceptions ne peuvent pas être gérées et l'exception stackoverflow en fait partie. Le sujet est discuté ici . C'est peut-être ce qui se passe dans votre cas.

4
Guish