[pyar] Timeouts para codigo de terceras partes: PyThreadState_SetAsyncExc?

Andres Riancho andres.riancho en gmail.com
Mar Ene 6 15:35:42 ART 2015


2015-01-06 15:31 GMT-03:00 Roberto Alsina <ralsina en netmanagers.com.ar>:
> On 06/01/15 15:14, Andres Riancho wrote:
>>
>> Al fin termine haciendo esto [0]:
>>
>>   * Creo un multiprocessing.Pool
>>   * Creo un "shared dict" donde el subproceso guarda que es lo que esta
>> procesando y su pid [1]
>>   * El parsing se hace en el subproceso, por medio del pool. El main
>> process se queda esperando a que el subprocess termine [2]
>>   * En caso de que no termine en menos que el timeout, se mata al
>> proceso usando la informacion guardada en [1](*)
>>   * Ya que puede haber varios procesos en el pool, hay una minima sync
>> para que dos distintos threads del main process no manden a parsear la
>> misma cosa [3], esto lo arme con eventos.
>>
>> Lo que no me gusto de mi implementacion:
>>
>>    * `os.kill(pid, signal.SIGTERM)`, en alguna race condition extraña,
>> puede llegar a matar un proceso que no tiene nada que ver con w3af,
>> oops!
>
>
> Por eso no tenés que matar los procesos del pool así, si no con
> Process.terminate()

No encontre una mejor manera de saber quien del pool esta corriendo
que cosa como para matarlo

Alguna idea de como hacerlo para hacer un Process.terminate() ?

>
>>    * No investigue suficiente sobre el Pool, pero asumo que va a
>> bancarse que le mate los hijos, spawnear nuevos, no tener memory
>> leaks, etc.
>>
>> Ya que en los parsers el "dom" generado por lxml no se requiere en
>> todos los casos lo que hice fue que solo en el main process se llame a
>> get_dom() , por lo que no tengo problemas con la serializacion
>>
>> (*) No encontre una mejor manera de saber quien del pool esta
>> corriendo que cosa como para matarlo
>>
>> [0]
>> https://github.com/andresriancho/w3af/blob/166dbff350f4922e0c1210d6348c2d30c5678ca2/w3af/core/data/parsers/parser_cache.py
>> [1]
>> https://github.com/andresriancho/w3af/blob/166dbff350f4922e0c1210d6348c2d30c5678ca2/w3af/core/data/parsers/parser_cache.py#L234
>> [2]
>> https://github.com/andresriancho/w3af/blob/166dbff350f4922e0c1210d6348c2d30c5678ca2/w3af/core/data/parsers/parser_cache.py#L137
>> [3]
>> https://github.com/andresriancho/w3af/blob/166dbff350f4922e0c1210d6348c2d30c5678ca2/w3af/core/data/parsers/parser_cache.py#L186
>>
>> 2015-01-06 0:03 GMT-03:00 Alejandro Santos <listas en alejolp.com>:
>>>
>>> 2015-01-06 3:49 GMT+01:00 Alejandro Santos <listas en alejolp.com>:
>>>>
>>>> 2015-01-06 0:30 GMT+01:00 Andres Riancho <andres.riancho en gmail.com>:
>>>>>
>>>>>      Gracias por la buena propuesta, despues de enviar el email estuve
>>>>> viendo eso y creo que en una gran cantidad de casos sirve pero... a mi
>>>>> no me va a servir ya que la respuesta de la libreria es un objeto que
>>>>> NO se puede serializar, por lo que no lo puedo pasar entre el
>>>>> subproceso (multiprocessing.Process) y el proceso principal.
>>>>>
>>>>>      Alguna idea de como hacer un workaround de eso? Estuve leyendo un
>>>>> poco sobre multiprocessing.Namespace, pero no estoy seguro, deberia
>>>>> probarlo.
>>>>>
>>>> ¿Qué es lo que la librería devuelve, un file handle o socket? Contame
>>>> un poco más en detalle cómo funciona. Lo que podés hacer es mover tu
>>>> lógica de procesamiento dentro de bad_func.
>>>>
>>>> Por ejemplo, si tu librería devuelve un socket que tenés que usar,
>>>> hacele read y write dentro de bad_func.
>>>>
>>> Una alternativa sería que, en vez de tener un timeout, hacer un
>>> watchdog con una especie de ping dentro de bad_func. Usás una Queue
>>> para avisarle al proceso padre que la ejecución sigue funcionando, y
>>> cuando pasa determinado tiempo sin respuesta el padre mata al proceso
>>> hijo:
>>>
>>> import multiprocessing
>>> from Queue import Empty
>>> import time
>>>
>>> def exec_with_timeout(f, args, timeout):
>>>      Q = multiprocessing.Queue()
>>>      p = multiprocessing.Process(target=f, args=(Q, args))
>>>      p.start()
>>>      while p.is_alive():
>>>          try:
>>>              if not: Q.pop(True, timeout):
>>>                  break
>>>          except Empty:
>>>              break
>>>
>>>      if p.is_alive():
>>>          p.terminate()
>>>
>>> def bad_func(q, t):
>>>      while True:
>>>          time.sleep(t)
>>>          q.push(True) # Le avisamos al padre que todo OK.
>>>
>>> exec_with_timeout(bad_func, (5.0, ), 0.1)
>>>
>>>
>>>
>>>
>>> --
>>> Alejandro Santos
>>> _______________________________________________
>>> pyar mailing list pyar en python.org.ar
>>> http://listas.python.org.ar/listinfo/pyar
>>>
>>> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>>>
>>> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
>>> Argentina - http://www.usla.org.ar
>>
>>
>>
>
> _______________________________________________
> pyar mailing list pyar en python.org.ar
> http://listas.python.org.ar/listinfo/pyar
>
> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>
> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
> Argentina - http://www.usla.org.ar



-- 
Andrés Riancho
Project Leader at w3af - http://w3af.org/
Web Application Attack and Audit Framework
Twitter: @w3af
GPG: 0x93C344F3


More information about the pyar mailing list