2012-10-01 13 views
5

Estoy usando HtmlAgilityPack para analizar aproximadamente 200,000 documentos HTML.Solución temporal a StackOverflowException

No puedo predecir el contenido de estos documentos, sin embargo uno de esos documentos hace que mi aplicación falle con un StackOverflowException. El documento contiene este código HTML:

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

Hay aproximadamente 10.000 <li> elementos anidados así. Debido a la forma en que HtmlAgilityPack analiza HTML causa un StackOverflowException.

Lamentablemente, no se puede detectar una StackOverflowException en .NET 2.0 y posterior.

Me preguntaba si configurar un tamaño más grande para la pila de subprocesos, pero establecer un tamaño de pila más grande es un truco: mi programa usaría mucha más memoria (mi programa comienza unos 50 hilos para procesar HTML, todos estos hilos tendrían el mayor tamaño de pila) y tendrían que ajustarse manualmente si alguna vez se topa con una situación similar.

¿Hay alguna otra solución alternativa que pueda emplear?

+0

realmente.A menos que tenga ganas de cambiarse a una biblioteca diferente, no veo una mejor manera que aumentar el tamaño de la pila. Tal vez hay una manera de establecer el tamaño de la pila solo para la (s) hebra (s) que lo necesitan. –

Respuesta

2

Idealmente, la solución a largo plazo es parchear HtmlAgilityPack para usar una pila de montón en lugar de la pila de llamadas, pero sería una empresa demasiado grande para mí. He perdido temporalmente los detalles de mi cuenta de CodePlex, pero cuando los recupere, enviaré un informe de problema sobre el problema. También observo que este problema podría presentar una vulnerabilidad de ataque de denegación de servicio a cualquier sitio que use HtmlAgilityPack para desinfectar el HTML enviado por el usuario: un documento HTML anidado y excesivamente elaborado provocaría la muerte del proceso w3wp.exe.

Mientras tanto, pensé que la mejor manera de avanzar es anular manualmente el tamaño máximo de la pila de subprocesos. Me equivoqué en mi afirmación anterior de que un mayor tamaño de pila significa que todos los subprocesos consumen automáticamente esa memoria (parece que las páginas de memoria se asignan a una pila de subprocesos a medida que crece, no de una vez).

Hice una copia de la página <ol><li> y realicé algunos experimentos. Descubrí que mi programa falló cuando el tamaño de la pila era menor que 2^21 bytes, pero se logró un tamaño máximo de 2^22, eso es 4MB y en mi libro pasa como un hack "aceptable" ... por ahora.

5

Acabo de parchar un error que creo que es el mismo que su descripción. Subido el parche en el sitio del proyecto hap ...

http://www.codeplex.com/site/users/view/sjdirect (ver el parche en 3/8/2012)

O ver más documentación de la emisión y el resultado aquí ....

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

La solución real fue ... Agregado HtmlDocument.OptionMaxNestedChildNodes que pueden ajustarse para evitar StackOverflowExceptions que son causadas por toneladas de etiquetas anidadas. Lanzará una ApplicationException con el mensaje "El documento tiene más de X etiquetas anidadas. Es probable que esto se deba a que la página no cierra correctamente las etiquetas".

Cómo estoy usando Hap Después de 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); 
} 
No
Cuestiones relacionadas