0

I'm trying to write multithread program to calculate usage of processor. The problem is that i don't know how to safely end threads. I have to end them by signal SIGTERM and I tried while(flag), phread_exit(), exit(), return(void*)0 but non of them work. I need to end infinite loop and return to main function. I've got two results: Exiting the whole program or program stopped and do nothing. How can I solve it?

#include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <signal.h>
    #include <ctype.h>
    #include <unistd.h>
    #include <sys/sysinfo.h>
    #include <ctype.h>
    #include <malloc.h>
    #include <time.h>
    #include <semaphore.h>
    #include "cpudata.h"
    #include"cpu_result.h"
    #include "reader.h"
    #include "analyzer.h"
    #include "writer.h"
    #define NUM_THREADS 3 //Number of threads
    
    //Declaring variables as volatile
    volatile struct cpu_data *datax1;
    volatile struct cpu_data *datax2;
    volatile struct cpu_result *result;
    
    //Declaring semaphores
    sem_t sem1;
    sem_t sem2;
    sem_t sem3;
    volatile int flag=1;
    volatile int val[NUM_THREADS]={0,0,0};
    
    void handle_sigterm(int signum)
    {
       flag=0;
    }
    
    void *reader(void *ptr) //Thread to read
    { while(flag){
        sem_post(&sem3);
        sem_wait(&sem1);
        sleep(1);           //Make sure that semaphores changes value
        load_data(datax1);
        sleep(1);           //Making sure that values datax1 and datax2 are different
        load_data(datax2);  
    
        if(datax1==datax2)  //checking if values are different
            {   
            perror("Datas are the same \n");
            }
        }
        pthread_exit(val[0]);
    }
    
    void *analyzer(void *ptr)//Thread to calculate data
    {   while(flag){
        
            sem_post(&sem1);
            sem_wait(&sem2);
            sleep(1);//Make sure that semaphores changes value
            
            for(int i=0;i<NOPT+1;i++)
                {
                result[i]=calculate(datax1[i],datax2[i]);//calculating data
                }        
        }
        pthread_exit(val[1]);
    }
    void *writer(void *ptr)//thread to write data 
    {  while(flag){
        
    sem_post(&sem2);
    sem_wait(&sem3);
    sleep(1);//Make sure that semaphores changes value

    writeresult(result);
    printf("\n\n\n\n\n\n");
    }
    pthread_exit(val[2]);
}



int main(int argc, char **argv)
{

    struct sigaction action;
    memset(&action,0,sizeof(struct sigaction));
    action.sa_handler=handle_sigterm;
    sigaction(SIGTERM,&action,NULL);

    //Allocating memory for data
    datax1=(struct cpu_data *)malloc((NOPT+1)*sizeof(struct cpu_data));
    datax2=(struct cpu_data *)malloc((NOPT+1)*sizeof(struct cpu_data));
    result=(struct cpu_result *)malloc((NOPT+1)*sizeof(struct cpu_result));

    pthread_t thread[NUM_THREADS];//declaring threads
    //Initializing semaphores
    sem_init(&sem1,0,1);
    sem_init(&sem2,0,1);
    sem_init(&sem3,0,1);

    //creating threads
    pthread_create(&thread[0],NULL, &reader, NULL);
    pthread_create(&thread[1],NULL, &analyzer, NULL);
    pthread_create(&thread[2],NULL, &writer, NULL);

    //make sure threads are working
    for(int i=0;i<NUM_THREADS;i++){
        pthread_join(thread[0],NULL);
        pthread_join(thread[1],NULL);
        pthread_join(thread[2],NULL);
    }
    //stopping threads
    for(int i=0;i<NUM_THREADS;i++){
        pthread_cancel(thread[0]);
        pthread_cancel(thread[1]);
        pthread_cancel(thread[2]);
    }
    
    //freeing memory
    sem_destroy(&sem1);
    sem_destroy(&sem2);
    sem_destroy(&sem3);
    free(datax1);
    free(datax2);
    free(result);
    printf("SAFETY CLOSING");
    return 0;
}
ulanny
  • 1
  • 2
    Your loop to join the threads attempts to join each thread three times. You can only join a thread once. Your loop to cancel the threads only runs after the threads have terminated; they can no longer be cancelled. – Jonathan Leffler Aug 09 '22 at 12:10
  • Call `sem_post()` after changing `flag`. Check `flag` after `sem_wait()` in thread and don't forget to `sem_post()` either in thread before exit or after `pthread_join()`. – dimich Aug 09 '22 at 12:10
  • I remove the problem with join and removed pthread cancel but the problem remains. I don't actually understand what i should do with semaphores there – ulanny Aug 09 '22 at 17:05
  • Please post your updated code. – Nate Eldredge Aug 10 '22 at 04:46
  • 1
    You have a lot of data races. `volatile` is not suitable for variables that are to be accessed by multiple threads; you need an `_Atomic` and some careful study of how to use them correctly. Note this applies not only to the `datax` and `result` pointers but also to the members of the structs they point to. – Nate Eldredge Aug 10 '22 at 04:51

0 Answers0