Bartłomiej
Bartłomiej

Reputation: 31

How to Properly Exit Main Process from a Thread in C?

I am working on a C program that simulates a hair salon, and I'm facing an issue with terminating the main process from the simulation_timer_thread. The only way I can successfully exit the main process is by using the kill function, which is not ideal.

In my simulation_timer_thread, after displaying the message printf(RED "Simulation ended, you can exit the program.\n" RESET);, I try to use exit(EXIT_SUCCESS); to end the program, but it doesn't work as expected - the main process is still running and program is not ended - there is still existing thread (it is not a problem closing it does not really help) and one process of program.

However, I can properly terminate the program in the koniec function and in the signal handler for a quick exit. This leads me to believe that there might be something specific to how the thread is structured that's preventing the program from exiting correctly.

Could anyone help me understand why I can't exit the main process from the simulation_timer_thread using exit()? Any insights or suggestions for a better approach to handle this would be greatly appreciated!

Thank you! Sorry for half of code in polish language ;/


char menu = 0;
    while (menu != '3' /*&& !koniec_symulacji*/)
    {
        printf(CYAN "1 - Zakończ pracę fryzjera\n");
        printf("2 - Natychmiastowo zamknij salon\n");
        printf("3 - Zwolnij zasoby i zakończ program\n" RESET);

        while (getchar() != '\n')
            ; // Czeszczenie bufora
        while (scanf("%c", &menu) != 1)
            ;

        switch (menu)
        {
        case '1':
            zabij_fryzjera(); // sygnał 1 kończy pracę jednego fryzjera
            break;
        case '2':
            sig_handler_int(0); // sygnał 2 kończy natychmiastowo pracę wszystkich klientów
            break;
        case '3':
            koniec(0); // zamyka program, zwalniając ps i ipcs
            break;
        default:
            printf(RED "Niepoprawna opcja\n" RESET);
            break;
        }
    }
    // pthread_join(timer_thread, NULL);
    // return 0;
}
...
void *simulation_timer_thread(void *arg)
{
    if (TP > 0)
    {
        sleep(TP); // Jeśli TP (czas opóźnienia otwarcia salonu) > 0, czekamy przez TP sekundy - domyślnie sleep(TP)
    }
    printf(YELLOW "Salon otwarty.\n" RESET);                                                                   // Informacja o otwarciu salonu
    sem_setval(poczekalnia_semafor, K);                                                                        // Inicjalizacji poczekalni - ilość K wolnych miejsc
    printf(YELLOW "Zainicjalizowano poczekalnię, ilość miejsc: %d.\n" RESET, sem_getval(poczekalnia_semafor)); // Informacja o inicjalizacji poczekalni

    int remaining = sim_duration; // Zmienna do przechowywania czasu pozostałego do zakończenia symulacji
    while (remaining > 0)         // Pętla działa dopóki nie minie czas symulacji
    {
        printf(MAGENTA "Czas pozostały: %d s\n", remaining); // Informacja o pozostałym czasie
        sleep(1);                                            // Symulacja upływu czasu - MUSI BYĆ USTAWIONY CZAS 1
        remaining--;                                         // Zmniejszenie liczby pozostałych sekund
    }
    sem_setval(poczekalnia_semafor, 0); // NALEŻY ZAKOMENTOWAĆ GDY SLEEP(0) Zamknięcie poczekalni po upływie czasu - równoznaczne z zamknięciem salonu - kolejni klienci nie wejdą
    printf(YELLOW "Salon zamknięty.\n" RESET);
    zabij_klientow();
    zabij_fryzjerow();
    zwolnij_zasoby_kierownik();
    printf(RED "Symulacja zakończona można zakończyć program.\n" RESET);
    // koniec_symulacji = 1;
    //  pthread_cancel(timer_thread);
    //   pthread_join(timer_thread, NULL);
    //   exit(EXIT_SUCCESS);
    // return NULL;
    //   kill(getpid(), SIGKILL);
}

void zabij_klientow()
{
    for (int i = 0; i < P; i++) // zabicie wszystkich klientów
    {
        kill(klienci[i], 2); // 2 - SYGNAŁ SIGINT
    }
    wait_for_process(P);
}

void zabij_fryzjerow()
{
        for (int i = 0; i < F; i++) // zabicie wszystkich fryzjerów
        {
            kill(fryzjerzy[i], 1); // 1 - SYGNAŁ SIGHUP
        }
        wait_for_process(F);
}

void zwolnij_zasoby_kierownik() // funkcja zwalniająca wszelkie zasoby
{
    //deleting semaphores, shared memory and message queue
    usun_kolejke_komunikatow(msg_qid);
    usun_semafor(kasa_semafor);
    usun_semafor(fotele_semafor);
    usun_semafor(poczekalnia_semafor);
    odlacz_pamiec_dzielona(kasa);
    usun_pamiec_dzielona(shm_id);
    printf(YELLOW "Zasoby zwolnione\n" RESET);
}

Link to whole file if needed: https://github.com/bartekzadlo/SO_Salon_Fryzjerski/blob/main/kierownik.c

What I found is that the process is waiting for input: strace -p 7486 strace: Process 7486 attached read(0,

To resolve this issue, I tried:

Using pthread_cancel and pthread_join: I attempted to cancel the timer thread and then join it in the main function, but this did not effectively terminate the main process.

Upvotes: 3

Views: 66

Answers (0)

Related Questions