billybiset / fud

Automatically exported from code.google.com/p/fud
GNU General Public License v3.0
1 stars 0 forks source link

bug en la interactividad de FuD #5

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Descripcion del problema
    El servidor envia JobUnits a sus clientes conectados, cuando uno de ellos recibe este trabajo inmediatamente se pone a trabajar en el y cuando termina le envia un resultado final de dicho trabajo al servidor. La nueva feature implementada permite al cliente enviar mensajes intermedios en medio del procesamiento. El problema surgue cuando del lado servidor estos mensajes llegan corruptos, lo cual el servidor instantaneamente descontecta a este cliente. Esto no deberia suceder.

¿ Cual es el problema ?
El cliente termina abruptamente porque el servidor lo desconecta, debido a que 
le llega un mensaje corrupto de este cliente.

¿ Cuando se manifiesta ?
Se manifiesta en un tiempo arbitrario, pero siempre se manifiesta.

¿ Como se manifiesta el bug ?
Las salidas de error por consola son 3, las cuales se pueden observar en la 
captura de pantalla tomada (ver abajo).
En el log (ver abajo), el problema siempre se expresa con el mismo mensaje, que 
indica que algun mensaje llega corruptamente, el cual es "Error receiving 
message: Header does not exist.". Esta salida es loggeada en el metodo 
ClientProxy::handle_response el cual se da cuando el header es invalido.

Captura de pantalla: http://s1.postimage.org/9tpwtl7k9/client_output.jpg
Log: http://pastebin.com/DYbprriJ

Resultado esperado
    Lo que deberia ocurrir normalmente es que el cliente siga trabajando (a medida que el servidor le da tareas) y que cada mensaje que envie (ya sea un mensaje intermedio o el resultado mismo) sea valido. El cliente solo debe terminar su ejecucion cuando el server lo desconecte, ya que se han terminado el total de los trabajos.

Pasos para reproducir el bug:
(Recordar que FuD depende de la libreria boost y de mili)

1. cd $SRC_DIR
2. svn checkout http://fud.googlecode.com/svn/branches/FuD-duplex fud-duplex
3. cd $BUILD_DIR/
4. mkdir fud-duplex
5. cd fud-duplex
6. cmake -Dmiddleware=ana -DCMAKE_BUILD_TYPE=Debug -Dapps=ON 
$SRC_DIR/fud-duplex/
7. make
8. En una terminal (server), hacer esto:
   cd $BUILD_DIR/fud-duplex/apps/counter-msg/server
   ./counter-msg
9. En otra terminal (client), hacer esto:
   cd $BUILD_DIR/fud-duplex/apps/counter-msg/client
   ./counter-client-msg

Versiones de software utilizados:
Ubuntu Linux 10.10 kernel 2.6.35-22-generic
g++ 4.4.5
mili r211
boost 1.42

Original issue reported on code.google.com by marjobe on 21 Apr 2011 at 11:25

GoogleCodeExporter commented 9 years ago
Otro sintoma:
Si al trabajo de procesamiento lo realiza el thread que escucha mensajes, el 
bug no se manifiesta. Pero esta implementacion no es correcta ya que el thread 
queda ocupado haciendo el trabajo y no puede recibir nuevos mensajes del 
servidor.

Original comment by marjobe on 21 Apr 2011 at 11:51

GoogleCodeExporter commented 9 years ago
Hay dos opciones a alto nivel: sale mal, o llega mal.
Este último comentario (http://code.google.com/p/fud/issues/detail?id=5#c1) 
confirma entonces que sale bien?

Cuál es la primer función que saca del socket?

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 1:05

GoogleCodeExporter commented 9 years ago
X fav agregar links al código, a las funciones relevantes.

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 1:08

GoogleCodeExporter commented 9 years ago
En respuesta al comentario 2.
Visto el sintoma, en el comentario 1, sabemos que en ese caso los paquetes 
salen bien (y llegan bien). En cambio, cuando el procesamiento lo hace el 
thread principal 
(http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/client/distr
ibution_client.cpp#61) el error se manifiesta, por lo que en nuestra opinion: 
los paquetes salen mal desde el cliente.

Envio y recepcion de paquetes lo confiamos a ANA:
la funcion que envia es 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/client/ana_distribution.cpp#69 y
la funcion que el listener llama cuando se recibe es 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/client/ana_distribution.cpp#84

Original comment by marjobe on 22 Apr 2011 at 12:39

GoogleCodeExporter commented 9 years ago
No entiendo el razonamiento:

emisor -> receptor:   MAL
emisor -> receptor2:  BIEN     (receptor2 sería cuando cambian el thread)

Por qué deducen que el problema está en el emisor, cuando cambiando el 
receptor funciona?

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 5:36

GoogleCodeExporter commented 9 years ago
pls see review comments in http://code.google.com/p/fud/source/detail?r=526

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 5:46

GoogleCodeExporter commented 9 years ago
Respuesta comentario 5.

Tener en cuenta que el escenario del bug es cuando el cliente envia mensajes 
intermedios al servidor, por lo tanto, el emisor es el cliente y receptor es el 
servidor.

Seria asi:

emisor  -> receptor:  MAL
emisor2 -> receptor:  BIEN   (emisor2 seria cuando el thread dedicado a 
escuchar largado aca 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/client/ana_distribution.cpp#60 hace todo el trabajo)

Dado el grafico de arriba, deducimos que el problema esta en el emisor ya que 
cambiando al emisor2, funciona.

Original comment by marjobe on 22 Apr 2011 at 6:26

GoogleCodeExporter commented 9 years ago
OK, por favor expliquen (de ser posible con un diff) cuándo funciona y cuándo 
no, porque no logro distinguir la diferencia en el código.
Por otro lado, xfav implementen las recomendaciones que hice en el código, 
especialmente los checkeos (de código de error, de mili::substr, etc.).
Consideren ADEMAS, y luego de estos cambios de código, correr todo con 
valgrind para verificar que no estén leyendo un paquete liberado y por lo 
tanto lean basura.
Todo tiene olor a un mutex de menos.

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 6:39

GoogleCodeExporter commented 9 years ago
(agreguen el diff attacheado acá xfav, y expliquen la dirección del diff: 
buggy->working, o al revés)

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 6:40

GoogleCodeExporter commented 9 years ago
La funcion 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/client/ana_distribution.cpp?spec=svn526&r=526#84 es el punto de entrada del 
cliente, la cual se ejecuta cuando llega un mensaje entrante.

La idea de la implementacion (que no funciona) es meter el mensaje que llega en 
una cola, que luego otro thread (el encargado de procesar trabajos) sacara para 
su posterior tratamiento.

El diff adjunto cambia el comportamiento de la implementacion explicada arriba, 
de forma que el mensaje entrante ahora NO es insertado en una cola, sino que 
recibe y procesa el trabajo el mismo listener (por lo que en este caso solo 
hablamos de un solo thread que hace todo).

El problema de este parche es que NO es una solucion valida ya que tenemos que 
tener al listener apto para la escucha de otros mensajes en el medio del 
procesamiento de un trabajo.

[ver working-fud.diff]

Original comment by marjobe on 22 Apr 2011 at 7:46

Attachments:

GoogleCodeExporter commented 9 years ago
Ahora sí, CLARÍSIMO. Lo analizamos. Buen desarrollo del issue.

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 7:49

GoogleCodeExporter commented 9 years ago
Por favor mientras tanto proceder con los cambios de código recomendados.

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 7:50

GoogleCodeExporter commented 9 years ago
Ok. Anda haciendo un update porque ya estuvimos tapando unos warnings.
Y seguiremos con las otras recomendaciones de chequeo...

Original comment by marjobe on 22 Apr 2011 at 7:52

GoogleCodeExporter commented 9 years ago
Con esto parecería ser que las opciones son:
a) el problema está en la inserción en la cola (add_message)
b) en el momento, o después de, la extracción de la cola (el otro thread).

Ahora hay que determinar de qué lado está el problema, en este sentido.

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 7:54

GoogleCodeExporter commented 9 years ago
(agrego)
c) el problema está tanto en la inserción o extracción de la cola, 
indiferentemente, POR SER UN PROBLEMA DE SINCRONIZACIÓN de la misma.

Original comment by danielgutson@gmail.com on 22 Apr 2011 at 8:06

GoogleCodeExporter commented 9 years ago
Por favor pega un link al add_message. El google code parece buscar sobre trunk 
 nomas.

Como te decia, mi impresion es que la memoria que termina usando para el 
mensaje se dealoca, por algun problema asociado a los buffers y el 
multi-threading.

Como nota, cuando ANA llama a tu handle_receive te pasa un buffer que en 
realidad es un auto_ptr:
http://code.google.com/p/ana-net/source/browse/trunk/src/api/buffers.hpp#172
http://code.google.com/p/ana-net/source/browse/trunk/src/api/buffers.hpp#49

El auto_ptr se destruye, junto con su memoria de soporte, en algun momento 
despues de q termina handle_receive, provisto que vos no hayas copiado el 
puntero, o sea, que si usas:
buffer->base() para memorizarte la base del buffer, eventualmente ese char* 
queda apuntando a memoria no allocada.

Original comment by billybiset on 27 Apr 2011 at 1:01

GoogleCodeExporter commented 9 years ago
Otro sintoma o solucion ?

Comentando este set_timeouts: 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/client/ana_distribution.cpp#59 funka !

A partir de la premisa de que no sabemos cuanto tiempo puede el cliente tardar 
mandando mensajes al servidor, pienso que la solucion es sacar esta linea o 
subir exageradamente el tiempo del timeout.

Original comment by marjobe on 2 May 2011 at 2:23

GoogleCodeExporter commented 9 years ago
Hiciste las modificaciones de código que sugerí?
Por favor, prolijamente un paso por vez.

Original comment by danielgutson@gmail.com on 2 May 2011 at 5:18

GoogleCodeExporter commented 9 years ago
Con respecto a las modificaciones de código que sugeriste: algunas fueron 
implementadas r527 y las demas las hice pero no las subi. Igual el 
comportamiento del bug no varió.

Lo que si modificó el comportamiento del bug es lo enunciado en el comment 17. 
Dame una opinion.

Original comment by marjobe on 2 May 2011 at 7:44

GoogleCodeExporter commented 9 years ago
No tengo aún el análisis suficiente para relacionar el c17 y el c10. Billy?

En cuanto a las modificaciones sugeridas, me refería especialmente a si 
(ahora?) que checkeás el código de error, reporta algo.

Original comment by danielgutson@gmail.com on 2 May 2011 at 7:52

GoogleCodeExporter commented 9 years ago
Un pedido: podrías resumir porfa cuáles son los threads involucrados, tanto 
del lado del cliente como del servidor, para terminar de entender c17 y c10?

Básicamente: threads involucrados (rol que cumple), en dónde corre, timeouts, 
y queues.

Me pierdo en qué timeouts de qué handle de qué cosa.

Original comment by danielgutson@gmail.com on 2 May 2011 at 7:56

GoogleCodeExporter commented 9 years ago
Un pedido: podrías resumir porfa cuáles son los threads involucrados, tanto 
del lado del cliente como del servidor, para terminar de entender c17 y c10?

Básicamente: threads involucrados (rol que cumple), en dónde corre, timeouts, 
y queues.

Me pierdo en qué timeouts de qué handle de qué cosa.

Original comment by danielgutson@gmail.com on 2 May 2011 at 7:56

GoogleCodeExporter commented 9 years ago
Sobre c17:

Los timeouts de ANA se usan para lo siguiente:
Le 'seteas' un timeout de 10 segundos a las operaciones, entonces si te mandas 
a enviar algo y para los 10 segundos no se termino de mandar, te informa que 
hubo timeout, conviene para conexiones malas. Su valor deberia ser empirico 
segun el uso que se le da. Quizas 10 segundos para mensajes grandes es poco, se 
pueden no poner timeouts (comentando esa linea) o usar timeouts relativos al 
tamaño del mensaje:

http://code.google.com/p/ana-net/source/browse/trunk/src/api/timers.hpp#238

y

http://code.google.com/p/ana-net/source/browse/trunk/src/api/timers.hpp#113

(se puede poner, por ej, 1 segundo por cada kilobyte o algo raro asi)

El miercoles analizo la relacion c17 / c20, estoy pasado entre mudanza y 
problemas de internet.

Original comment by billybiset on 2 May 2011 at 7:59

GoogleCodeExporter commented 9 years ago
Marian, para ver threads, en gdb:

info threads

t N (donde N es el thread que queres)

ANA corre un thread para llamar los callbacks por cada operacion de run() sobre 
el objeto ana::client o ana::server.

Original comment by billybiset on 2 May 2011 at 8:00

GoogleCodeExporter commented 9 years ago
lo mejor es que attachees el output del siguiente comando en gdb:
t a a bt

(uso la primer letra de cada comando: [t]hreads [a]pply [a]ll backtrace)

a lo mejor quieras hacer antes:
set logging file mariano
set logging on
set height 0

y simplemente después attachear acá el archivo mariano

Original comment by danielgutson@gmail.com on 2 May 2011 at 8:11

GoogleCodeExporter commented 9 years ago
Con respecto a c21, threads involucrados:
Lado cliente
* Thread principal: ejecuta este metodo --> 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/client/distri
bution_client.cpp#61 que basicamente chequea la queue de mensajes y segun el 
tipo de msg hace algo.
* Thread escuchador (nace aca 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/client/ana_distribution.cpp#58) y es de ANA, cada vez que llega un msg del 
server ejecuta handle_receive --> 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/client/ana_distribution.cpp#82 la cual mete a la queue de mensajes el 
paquete que viene desde del server. Este thread setea(ba) el timeout de ANA en 
10 segundos (explicacion del timer en c23).

Lado servidor
* Thread escuchador (nace aca 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/server/ana_clients_manager.cpp#56) es de ANA, cada vez que llega un mensaje 
desde un cliente llama a handle_receive 
(http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/
ana/server/ana_clients_manager.cpp#69), el cual llama al handle_response del 
cliente en particular 
(http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/server/clien
t_proxy.cpp#73).

Como adjuntos estan los outputs del gdb (segun c25) del server y del client.

De todas formas: el bug ESTA SOLUCIONADO. O para uds no ?

Original comment by marjobe on 2 May 2011 at 9:09

Attachments:

GoogleCodeExporter commented 9 years ago
No sé si el bug está solucionado, porque no sé siquiera si sabemos 
exactamente cuál es el problema.

La idea de los attachments q te dije era ver el bt (por eso "t a a bt"); lo q 
attacheaste no dice nada :(

Con esto ya sí podemos terminar de hacer el análisis.

Original comment by danielgutson@gmail.com on 2 May 2011 at 9:43

GoogleCodeExporter commented 9 years ago
Workaround

Una solucion alternativa para este bug es NO setear un tiempo fijo por cada 
operacion de envio del cliente. Este método, que setea una determinada 
tolerancia de tiempo, pertenece a la libreria ANA.
¿ Como se implementó esta solución alternativa ?
Comentando esta linea --> 
http://code.google.com/p/fud/source/browse/branches/FuD-duplex/src/middlewares/a
na/client/ana_distribution.cpp#58 . Fue hecho en r546.

Si se encuentra una solución definitiva, se deberia descomentar la misma 
linea, por lo que FuD funcionaria con el set_timeouts de tiempo fijo.

Original comment by marjobe on 10 May 2011 at 3:20