2

I'm doing an exercise for an exam, which asks me to create 2 processes (parent and child), each one must create N threads (N is provided by user) and a file (also the filename is provided by user). Then, each thread of the parent process takes strings from standard input and put them into a shared buffer, while each thread of the child process should take those strings and put them into the file created. Then, SIGINT should list the strings put into the file (ctrl-c).

Now, i managed to create processes, threads, file and so on, i can give strings from standard input, but it won't be read from the child processes. I know for sure there's something wrong in using mutexes for synchronizing threads and processes.

Anyone has advices?

#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 4096

FILE *file;
int fd;
char *filename;
char *N;
pid_t pid;
pthread_t *tid;
pthread_mutex_t* read_mutex;
pthread_mutex_t* write_mutex;
char **memory_segments;
int write_counter = 0;
int num_threads;

void parent_handler(int signo)
{
    printf("Signal captured %d forwarding to child (pid %d)\n", signo, pid);
    kill(pid, signo);
}

void child_handler(int signo)
{
    char buff[1024];
    
    sprintf(buff, "cat %s\n", filename);
    system(buff);
}   

void* child_function(void *dummy)
{
    long me = (long)dummy;
    
    printf("Child thread #%ld started\n", me);
    
    while(1)
    {
        if ((pthread_mutex_lock(read_mutex + me)) == -1)
        {
            printf("Error while locking mutex\n");
            exit(EXIT_FAILURE);
        }
        
        printf("Child thread #%ld read string: %s\n", me, memory_segments[me]);
        
        fprintf(file, "%s", memory_segments[me]);
        fflush(file);
    
        if ((pthread_mutex_unlock(write_mutex + me)) == -1)
        {
            printf("Error while locking mutex\n");
            exit(EXIT_FAILURE);
        }
    }
}

void* parent_function(void *dummy)
{
    long me = (long)dummy;
    //printf("Parent thread #%ld started\n", me);
    
    while(1)
    {   
        //printf("me: %ld\n", me);
        //printf("write_counter: %d\n", write_counter);
        
        if(write_counter == me)
        {   
            printf("THREAD[%ld]: ", me);
            fflush(stdout);
        }
        
        if ((pthread_mutex_lock(write_mutex + me)) == -1)
        {
            printf("Error while locking mutex\n");
            exit(EXIT_FAILURE);
        }
        
        fgets(memory_segments[me], SIZE, stdin);
        printf("Parent thread #%ld wrote: %s", me, memory_segments[me]);
        
        if ((pthread_mutex_unlock(read_mutex + me)) == -1)
        {
            printf("Error while unlocking mutex\n");
            exit(EXIT_FAILURE);
        }
        
        me = (me + 1) % num_threads;
        write_counter = (write_counter + 1) % num_threads;
    }
}

int main(int argc, char** argv)
{       
        if(argc != 3)
        {
            printf("Usage: %s filename num_threads\n", argv[0]);
            exit(EXIT_FAILURE);
        }
        
        num_threads = strtol(argv[2],NULL,10);
        filename = argv[1];
        
        if((fd = open(argv[1], O_CREAT | O_RDWR | O_TRUNC, 0660)) == -1)
        {
            printf("Error creating file %s\n", argv[1]);
            exit(EXIT_FAILURE);
        }
        
        if((file = fdopen(fd, "w+")) == NULL)
        {
            printf("Error opening file %s\n", argv[1]);
            exit(EXIT_FAILURE);
        }
        
        if((memory_segments = malloc(sizeof(char *) * num_threads)) == NULL)
        {
            printf("Error allocating space for memory_segments\n");
            exit(EXIT_FAILURE);
        }
        
        for(size_t i = 0; i < num_threads; i++)
        {
            if((memory_segments[i] = (char *)mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == NULL)
            {
                printf("Error mapping memory_segments\n");
                exit(EXIT_FAILURE);
            }
        }
        
        read_mutex = malloc(sizeof(pthread_mutex_t) * num_threads);
        write_mutex = malloc(sizeof(pthread_mutex_t) * num_threads);
        tid = malloc(sizeof(pthread_t) * num_threads);
        
        for(size_t i = 0; i<num_threads; i++)
        {
            if((pthread_mutex_init(read_mutex + i, NULL)) == -1)
            {
                printf("Error while initializing mutex\n");
                exit(EXIT_FAILURE);
            }
        }
        
        for(size_t i = 0; i<num_threads; i++)
        {
            if((pthread_mutex_init(write_mutex + i, NULL)) == -1)
            {
                printf("Error while initializing mutex\n");
                exit(EXIT_FAILURE);
            }
        }
        
            
        for(size_t i = 0; i < num_threads; i++)
        {
            if((pthread_mutex_lock(read_mutex + i)) == -1)
            {
                printf("Error while locking mutex\n");
                exit(EXIT_FAILURE);
            }
        }
                
        pid = fork();
        
        if(pid == 0)
        {
            signal(SIGINT, child_handler);
            
            printf("Hello, i'm the child process!\n");
            for(size_t i = 0; i < num_threads; i++)
            {
                if((pthread_create(tid + i, NULL, child_function, (void *)i)) == -1)
                {
                    printf("Error while creating child threads\n");
                    exit(EXIT_FAILURE);
                 }
             }
         }
        else
        {
            signal(SIGINT, parent_handler);
            
            printf("Hello, i'm the parent process!\n");
            for(size_t i = 0; i < num_threads; i++)
            {
                sleep(1);
                if((pthread_create(tid + i, NULL, parent_function, (void *)i)) == -1)
                {
                    printf("Error while creating child threads\n");
                    exit(EXIT_FAILURE);
                 }
             }
         }
         
         while(1) pause();
}

I'm expecting to read strings from the child function each time i type new lines on command line.

2

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.