Contourner une exception StackOverflowException

html-agility-pack stack-overflow

Question

J'utilise HtmlAgilityPack pour analyser environ 200 000 documents HTML.

Je ne peux pas prédire le contenu de ces documents. Toutefois, un tel document entraîne l'échec de mon application avec une StackOverflowException . Le document contient ce code HTML:

<ol>
    <li><li><li><li><li><li>...
</ol>

Il y a environ 10 000 <li> éléments imbriqués comme ça. En raison de la façon dont HtmlAgilityPack analyse HTML, une StackOverflowException .

Malheureusement, une exception StackOverflowException n'est pas capturable dans .NET 2.0 et versions ultérieures.

Je me demandais vraiment de définir une taille plus grande pour la pile du thread, mais le fait de définir une taille de pile plus grande est un hack: cela obligerait mon programme à utiliser beaucoup plus de mémoire (mon programme démarre environ 50 threads pour le traitement HTML, donc tous ces threads). augmenterait la taille de la pile) et aurait besoin d’être ajusté manuellement si jamais il se retrouvait dans une situation similaire.

Existe-t-il d'autres solutions que je pourrais employer?

Réponse acceptée

Idéalement, la solution à long terme consiste à appliquer un patch à HtmlAgilityPack pour utiliser une pile de tas au lieu de la pile d'appels, mais ce serait une entreprise trop lourde pour moi. J'ai temporairement perdu les détails de mon compte CodePlex, mais lorsque je les récupère, je soumets un rapport de problème sur le problème. Je remarque également que ce problème pourrait présenter une vulnérabilité d’attaque par déni de service pour tout site utilisant HtmlAgilityPack pour assainir le code HTML soumis par l’utilisateur. Un document HTML trop imbriqué spécialement construit ferait mourir le processus w3wp.exe.

Dans l’intervalle, j’ai pensé que la meilleure solution consiste à remplacer manuellement la taille maximale de la pile de threads. Je me suis trompé dans ma déclaration précédente selon laquelle une taille de pile plus grande signifie que tous les threads consomment automatiquement cette mémoire (il semble que les pages de mémoire sont allouées à une pile de thread au fur et à mesure de sa croissance, et non en une seule fois).

J'ai fait une copie de la page <ol><li> et lancé quelques expériences. J'ai trouvé que mon programme a échoué lorsque la taille de la pile était inférieure à 2^21 octets, mais qu'une taille maximale de 2^22 réussi - c'est 4 Mo et, dans mon livre, passe comme un hack "acceptable" ... pour l'instant.


Réponse populaire

Je viens de corriger une erreur qui, je crois, est la même que celle que vous décrivez. Téléchargé le correctif sur le site du projet hap ...

http://www.codeplex.com/site/users/view/sjdirect (voir le correctif du 3/8/2012)

Ou voir plus de documentation sur le problème et le résultat ici ....

https://code.google.com/p/abot/issues/detail?id=77

Le correctif actuel était ... Ajout de HtmlDocument.OptionMaxNestedChildNodes pouvant être configurés pour empêcher StackOverflowExceptions causés par des tonnes de balises imbriquées. Une exception ApplicationException contenant le message "Le document contient plus de X balises imbriquées. Cela est probablement dû au fait que la page ne ferme pas les balises correctement".

Comment j'utilise Hap After Patch ...

HtmlDocument hapDoc = new HtmlDocument();
hapDoc.OptionMaxNestedChildNodes = 5000;//This is what was added
string rawContent = GETTHECONTENTHERE
try
{
    hapDoc.LoadHtml(RawContent);    
}
catch (Exception e)
{
    //Instead of a stackoverflow exception you should end up here now
    hapDoc.LoadHtml("");
    _logger.Error(e);
}



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi