sisoputnfrba / foro

Foro de consultas para el trabajo práctico
151 stars 7 forks source link

Thread mueren al iniciarlos y Valgrind tira el error "the 'impossible' happened: Killed by fatal signal" #3007

Closed ArgonzMatias closed 1 year ago

ArgonzMatias commented 1 year ago

Buenos días. Estoy con el síguiente problema. Hasta hace unos días mi kernel era un kernel común y corriente. Pero, de repente, decidió ser un asesino serial de hilos. Ahora dejando los chistes de lado, el día del checkpoint 3 mi kernel estaba funcionando con normalidad. Hace una inicializacion de los 4 hilos, uno para planificación corto plazo, largo plazo, para ejecutar los procesos y el ultimo para la finalización de procesos. Luego sigue a esperar las conexiones de consola. Sin embargo, después del checkpoint hice cambios al código pero no toque nada de estos hilos, los dejé como estaban. Le agregue logs mas que nada, cosas que no llegan a ejecutar todavia. Pero ahora al ejecutar kernel, se muere en la inicializacion de estos hilos. Al usar el debugger me di cuenta que el problema son los hilos porque me tira segmentación fault thread 4. Probé cambiar el orden en el que inició los hilos y mismo resultado solo que va variando el hilo que muere. Estos hilos tiene un while(1) y sus respectivos semáforos. Lo que no puedo entender es porque si antes me andaba ahora no. Ah y yo todavía tengo una branch donde tengo mi kernel anterior sin los cambios que realize, y ese kernel si me anda y la funcion inicializar_planificador esta igual. Nose si metí la pata con los nuevos cambios porque para mi no tienen nada que ver con mi problema, ni siquiera llega a ejecutar hasta esa parte. Adjunto todo lo que creo que es neceseario abajo para entender este problema. Espero sus consejos, gracias!

🔎 Búsqueda en foros

Mi sospecha, por lo que estuve leyendo en distintos issues, es que mis hilos están teniendo problemas de memoria. Pero no me doy cuenta ni donde es ni cómo solucionarlo porque no encuentro cual seria el error.

📝 Código relevante

Main Kernel

int main(int argc, char* argv[]) {
    kernel_configs = kernel_config_crear(PATH_CONFIGS);
         int socketKernel = iniciar_servidor_kernel(IP_KERNEL, kernel_configs->puerto_escucha);

    if(socketKernel == -1){
    log_error(kernelLogger, "no se pudo iniciar el servidor kernel");
    kernel_destruir(kernel_configs, kernelLogger);
    exit(-1);
    }
    inicializar_planificador();  //<- muere aca la funcion
        nueva_conex(socketKernel); 
         return 0;
          }

Incializador planificador

void inicializar_planificador(void){
        pthread_mutex_init(&nextPidMutex,NULL);
    int valorMultiprogramacion = kernel_configs->grado_max_multiprogramacion; 

    sem_init(&nuevosPcbsReady, 0, 0);
    sem_init(&grado_multiprogramacion, 0, valorMultiprogramacion);
    sem_init(&io,0,0);
    nextPid = 1;

    e_new = crear_estado(NEW);
    e_ready = crear_estado(READY);
    e_execute = crear_estado(EXECUTE);
    e_exit = crear_estado(EXIT);
    e_blocked = crear_estado(BLOCKED);

    pthread_t  th_corto_plazo;
    pthread_create(&th_corto_plazo, NULL, (void*) planificador_corto_plazo , NULL);
    pthread_detach(th_corto_plazo);

    pthread_t  th_execute_pcb;
    pthread_create(&th_execute_pcb, NULL, (void*) execute_pcb, NULL);
    pthread_detach(th_execute_pcb);

    pthread_t  th_largo_plazo;
    pthread_create(&th_largo_plazo, NULL, (void*) planificador_largo_plazo, NULL);
    pthread_detach(th_largo_plazo);

    pthread_t  freeProcesoExit;
    pthread_create(&freeProcesoExit, NULL, (void*)estado_end_liberar, NULL);
    pthread_detach(freeProcesoExit);
}

Lo que me tira el Debugger de Eclipse:

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe0a8) at src/kernel.c:56
56              kernel_configs = kernel_config_crear(PATH_CONFIGS);
[New Thread 0x7ffff7d75640 (LWP 7432)]
[New Thread 0x7ffff7574640 (LWP 7433)]

Thread 2 "kernel.out" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff7d75640 (LWP 7432)]
planificador_corto_plazo () at src/planificador.c:221
221                     sem_wait(e_ready->semaforoEstado);
(gdb) [Thread 0x7ffff7574640 (LWP 7433) exited]                                                     
[Thread 0x7ffff7d75640 (LWP 7432) exited]

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

Corto plazo

static void planificador_corto_plazo(void){

    while(1){
        sem_wait(e_ready->semaforoEstado);
        //codigo(...)
}

Largo Plazo

static void planificador_largo_plazo(void){

    while(1){
    sem_wait(&nuevosPcbsReady);
        sem_wait(&grado_multiprogramacion);   
    //coidgo(....)
    }
}

Estado end

static void estado_end_liberar(void){
    while(1){
        sem_wait(e_exit->semaforoEstado);
                //codigo (....)
    }
}

Execute_pcb

static void execute_pcb(void){
    while(1){
    sem_wait(e_execute->semaforoEstado);
    //codigo(...)
}
}

Crear Estado

estado_proceso* crear_estado(bandera_estado name){
    estado_proceso* e = malloc(sizeof(*e));
    //Otras inicializaciones de estados(...)
    e->semaforoEstado = malloc(sizeof(*(e->semaforoEstado)));
    sem_init(e->semaforoEstado,0,0);
    return e;
}

Inicializacion planificador antes de los cambios:

void inicializar_planificador(void){

    int valorMultiprogramacion = kernel_configs->grado_max_multiprogramacion; 
       sem_init(&nuevosPcbsReady, 0, 0);
       sem_init(&grado_multiprogramacion, 0, valorMultiprogramacion);

         e_new = crear_estado(NEW);
           e_ready = crear_estado(READY);
         e_execute = crear_estado(EXECUTE);
         e_exit = crear_estado(EXIT);
        e_blocked = crear_estado(BLOCKED);

pthread_mutex_init(&nextPidMutex,NULL);

pthread_t th_largo_plazo;
pthread_create(&th_largo_plazo, NULL, (void*) planificador_largo_plazo, NULL); // -> aca se crea el thread de estado_end_liberar 
pthread_detach(th_largo_plazo);

pthread_t th_corto_plazo;
pthread_create(&th_corto_plazo, NULL, (void*) planificador_corto_plazo, NULL);  // -> aca se crea el thread de execute_pcb 
pthread_detach(th_corto_plazo); 
}

💻 Logs

Probé usar valgrind y me marca que cuando importo la configuración del kernel me esta dando este error. Pero primero q no entiende porque me lo marca como mal específicamente esa línea y segundo no entiendo porque eso me mata al hilo. Estoy recien aprendiendo a usar la herramienta asi que nose si es un error simple pero no encontre solucion. Si comento la linea que me tira el error, me salta nuevamente el mismo error en la linea siguiente.

Codigo donde me tira el error:

static void kernel_config_iniciar(void* moduleConfig, t_config* config){
    kernel_config* kernelConfig = (kernel_config*)moduleConfig; 
    kernelConfig->ip_memoria = strdup(config_get_string_value(config, "IP_MEMORIA"));
    kernelConfig->ip_cpu = strdup(config_get_string_value(config, "IP_CPU"));
    //(mas configs que andan bien ...)
    kernelConfig->puerto_filesystem = strdup(config_get_string_value(config, "PUERTO_FILESYSTEM")); //-> aca me marca el error

Valgrind error en eclipse

--8936-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--8936-- si_code=1;  Faulting address: 0x954FD28;  sp: 0x100308de50

valgrind: the 'impossible' happened:
   Killed by fatal signal

host stacktrace:
==8936==    at 0x5803104A: ??? (in /usr/libexec/valgrind/helgrind-amd64-linux)
==8936==    by 0x5800B641: ??? (in /usr/libexec/valgrind/helgrind-amd64-linux)
==8936==    by 0x5807FCAC: ??? (in /usr/libexec/valgrind/helgrind-amd64-linux)
==8936==    by 0x580C9E70: ??? (in /usr/libexec/valgrind/helgrind-amd64-linux)

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable (lwpid 8936)
==8936==    at 0x484A919: malloc (in /usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so)
==8936==    by 0x492460E: strdup (string/./string/strdup.c:42)
==8936==    by 0x10BDE0: kernel_config_iniciar (/home/utnso/Desktop/tpSo/tp-2023-1c-Alpha-Centauri/kernel//src/kernel.c:177)
==8936==    by 0x10CAB1: config_init (/home/utnso/Desktop/tpSo/tp-2023-1c-Alpha-Centauri/utils/src/utils/utils.c:323)
==8936==    by 0x10BEB0: kernel_config_crear (/home/utnso/Desktop/tpSo/tp-2023-1c-Alpha-Centauri/kernel//src/kernel.c:188)
==8936==    by 0x10BA46: main (/home/utnso/Desktop/tpSo/tp-2023-1c-Alpha-Centauri/kernel//src/kernel.c:56)
client stack range: [0x1FFEFFE000 0x1FFF000FFF] client SP: 0x1FFF0004E0
valgrind stack range: [0x1002F8E000 0x100308DFFF] top usage: 18744 of 1048576
iago64 commented 1 year ago

Buenas! Cómo va?

Creo que tu problema es realmente simple y viene de la mano de que está terminando el hilo main y como termina el hilo principal de tu proceso, todos los hilos hijos van a morir también.

Lo que deberían hacer es que al menos el main se quede esperando un hilo que no termine, como por ejemplo, el que escucha las conexiones entrantes.

Saludos.-

ArgonzMatias commented 1 year ago

Buenas, es que es imposible que main se muera porque nueva_conex(socketKernel); (la ultima funcion que llama main) hace un loop infinito para que acepte todas las consolas. Te dejo el codigo de la funcion:

void nueva_conex(int socketEscucha){
    struct sockaddr cliente = {0};
    socklen_t aux = sizeof(cliente);
    for(;;){
    int clienteElegido = accept(socketEscucha, &cliente, &aux);
    if(clienteElegido > -1){
        int* socketCliente = malloc(sizeof(*socketCliente));
        *socketCliente = clienteElegido;
        crear_hilo_conex_entrante(socketCliente);
    } else{
        log_error(kernelLogger, "error en establecer conexion");
    }
}}
iago64 commented 1 year ago

Ok, entonces descartado que este terminando el proceso y por eso les matan los threads, los mismos se mueren porque tira seg fault el programa.

Por las dudas pregunto, para que estan haciendo strdup() cuando leen las config? Porque revisando nuevamente veo que el error viene justo con un strdup() al momento de levantar una config que me juego a que no la esta encontrando y por eso pincha porque les devuelve null el config_get_string_value()

Saludos.-

ArgonzMatias commented 1 year ago

Hola, ese strdup es justamente para que me lea el puerto como un char en vez de un char. Que despues cuando levanta el servidor, necesita ese char en la funcion getaddrinfo(). Por ejemplo hice lo mismo en el modulo consola y anda sin problema. Aparte es raro, porque el valgrind me marca eso como mal pero ni uso esa variable todavia porque no hice la conexion con filesystem, y no me marca como mal el uso de strdup en las otras variables anteriores que uso como ip_cpu, ip_memoria, etc... Me tome el trabajo de ademas chequear que devuelven las variables con el debugger y dan lo que corresponden. Tipo no me suena a que sea esto porque tenia la misma estructura antes y andaba joya.

Pero bueno aparte de todo esto, los hilos que creo no usan estas variables, porque son solamente las configuraciones de kernel. Estos threads se me mueren pq reciben la senial SIGSEGV de la nada.

Hice mas pruebas y llegue a estas conclusiones. Siempre me crea 3 hilos y falla en uno de esos 3. Siempre son los hilos que tienen en sus procesos los semaforos de los estados para empezar a correr el algoritmo, el planificador de largo plazo nunca me tira el error. Nose si tendra que ver, pero bueno revise esto y no parece que este mal. Lo unico que se me ocurre es que se quede sin memoria (pero no tiene sentido, porque no estoy usando mucho creo) o sea algo particular en mi comutadora. Ahora a la tarde vamos a probar con la compu de mis companeros a ver si ellos tienen el mismo error.

Alguna otra idea de que puede ser? Gracias

ArgonzMatias commented 1 year ago

Buenas, nose como pero magicamente ahora anda. Amo eclipse! Nose que era pero bueno. Gracias!