Closed diegohcanetti closed 5 months ago
Buenas! Cómo va?
Cuando decis rompe el send()
y el recv()
, puntualmente que error les esta tirando? Helgrind los va a ayudar solamente a ver que onda con los semáforos, pero si el problema es de memoria, la herramienta es Valgrind.
Saludos.-
Helgrind no nos está mostrando ninguna posible condición de carrera, no tenemos ni memory leaks ni segmention fault (sin embargo chequeamos y no nada definetly lost).
Al mencionar rompe, me refiero que nosotros lo que estamos haciendo como mostré antes es un send y recv entre el Kernel y la IO generica para que el proceso de Kernel sepa cuando termino el IO. Sin embargo, hay veces que funciona y hay veces que no, lo que dice helgrind es que el Kernel sigue esperando el mensaje de IO de que ya termino, pero la interfaz ya le hizo el send. Entonces no entendemos pq el Kernel no está recibiendo este "ping".
Buenas!
Vamos por partes, en primer lugar Helgrind no te va a mostrar absolutamente NADA porque estas en 2 procesos distintos, la herramienta es potente, pero no puede saber que esta pasando en otros procesos.
En segundo lugar, lo que tenes que buscar aca es ver como estas estableciendo la comunicación, y empezar a ver un poco el mapa completo del problema. Para que entiendas lo que te estoy diciendo, lo que yo veo es lo siguiente:
Por un lado lo tenemos al Kernel que en algún lugar del código que no esta subido en este issue le manda un paquete a la interfaz de IO con un Código de Operacion, el PID y el tiempo a esperar y asumo que el código de operación uds tienen un ENUM donde existe GENERICA_IO_SLEEP
y con esto podemos saber que lo que llego es la operación más simple de IO que es la de esperar X tiempo.
Veo que del paquete sacas de forma extraña 2 enteros, y cuando me refiero a que lo sacas de forma extraña es porque veo que tenes las siguientes líneas:
proceso_conectado = sacar_entero_de_paquete(&stream);
cantidad_tiempo = sacar_entero_de_paquete(&stream);
Y veo que le pasas la dirección del puntero stream
en lugar de quizas pasarle una copia o pasarle el mismo puntero.
Una vez terminado este tiempo, tenemos un envío del PID del proceso desde la interfaz al Kernel, aca del lado kernel deberíamos salir del recv()
y justo depsues de eso tenemos en la interfaz el mensaje: "El proceso: %d finalizo IO\n"
, que no entiendo porque lo tenes en un printf y no en un log_info
o log_trace
.
Ahora del lado kernel tenes el recv()
esperando que le llegue un mensaje y que no tiene un flag que solemos recomendarles que lo tengan en todos los llamados a recv()
como es el flag MSG_WAITALL
y aca veo que lo dejaste con 0 que no es el valor de MSG_WAITALL.
Escrito todo lo que estoy pensando, lo que no me termina de cerrar es, si te estas tomando el tiempo de debuggear las cosas para ver que datos estas mandando / recibiendo de ambos lados.
Saludos.-
Voy respondiendo las sugerencias/preguntas de a una:
Sin embargo nos sigue provocando errores el send y recv, cuál es el error:
Nosotros estamos haciendo dos IO_GEN_SLEEP, uno de 10 y otro de 1, en el config de ejemplo el tiempo de unidad de trabajo es de 250 por lo tanto el primer usleep es de (1000*10*250
) y el segundo es de (1000*1*250
), al ser tan rápido el sleep de esta segundo instrucción ocurre primero el send y después y el Kernel llega al recv, por lo tanto casi nunca "recibe nada". Intentamos probando diferentes flags y estrategias para manejar estos casos, pero no logramos corregir este problema.
Buenas! Cómo va?
A ver si entiendo un poco la situación porque no se si es que me perdí en algo o que pasó. Del lado Kernel uds deberían:
send()
para pedirle a la interfaz que ejecute la IO recv()
para esperar la respuesta
Por eso dije que no estaba viendo en el código que subieron que estuviera el send()
en ningún lado y que asumía que lo hacian antes.Del lado de la Interfaz de IO uds deberían:
recv()
send()
para avisarle al Kernel que terminaron.En el caso del código que esta de la interfaz, asumo que la función: recibir_paquete()
es la que tiene el recv()
.
En toda la secuencia que estoy mencionando, ambos recv()
deberían bloquear al proceso, por lo que, no te importa si llegaste antes al recv()
que al send()
del otro lado, vos deberías bloquearte esperando esa info.
Este tipo de problemáticas es uno de los motivos principales por el que nos ponemos molestos con el tema de los protocolos, me parece que algo esta fallando en la definición.
Saludos.-
Hola,
Gracias por tu explicación detallada. Sin embargo, quería aclarar que ya habíamos implementado las funciones de send() y recv() de acuerdo con la lógica que mencionaste desde hace dos semanas. Parece que hubo una confusión en la comunicación anterior, pero quería asegurarte de que esos aspectos estaban cubiertos en nuestra implementación. Vamos a seguir con otros aspectos del TP.
Saludos.-
Para el manejo de Interfaces hicimos que cada vez que una termina su operación haga un send y del lado del Kernel hay un recv que desencola al proceso de bloqueados de esa proceso y lo manda a Ready. Sin embargo con las pruebas que estuvimos haciendo las mayorías de las veces rompe al segundo send y recv, otras pasa la operación y en otras rompe en el primer IO_GEN_SLEEP. Haciendo pruebas, debuggeando e intentando diferentes soluciones no encontramos el problema exacto.
📝 Código relevante
Del lado del Kernel:
Del lado del IO:
🐛 Cómo reproducir el error
Estamos realizando la prueba de DEADLOCK del cuatrimestre pasado, pero descubrimos que podemos reproducir el error con un solo proceso con estas instrucciones: SET AX 1 WAIT REC1 IO_GEN_SLEEP impresora1 10 WAIT REC2 SET BX 1 SUM AX BX IO_GEN_SLEEP impresora1 1 SIGNAL REC2 SIGNAL REC1 EXIT
💻 Logs
Lo corrí con Helgrind y logré observar esto en el Kernel cuando corte la conexion: