1

I have some code in C which works perfectly on MacOS. Shortly, I've a process that takes a mutex, writes on a pipe, unlocks the mutex and send a signal to a condition variable. Then, there's another process which listens to this pipe and whenever gets a signal, reads the buffer and writes the content on a local file.

The problem is that the exact same code, doesn't work on Linux Ubuntu.

I tried to change the implementation of mutex and condition variable, following tips around the Internet, but didn't work.

Here some code for a better explanation:

Firstly, I initialize mutex and condition as process shared

    pthread_mutexattr_t mutexAttr = {};
    pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
    pthread_mutex_init(&mutex, &mutexAttr);

    pthread_condattr_t condAttr = {};
    pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
    pthread_cond_init(&condition, &condAttr);

This is the function which runs on the process that reads the pipe and writes to the file

    char buffer[8192];
    while(1) {
        bzero(buffer, sizeof buffer);
        pthread_cond_wait(&condition, &mutex);
        pthread_mutex_lock(&mutex);
        read(pipe_fd[0], buffer, sizeof buffer);
        _log(buffer);
        pthread_mutex_unlock(&mutex);
    }

And finally this is the code which runs on another process and writes on the pipe

    char *buffer = malloc(SIZE);
    sprintf(buffer, "name: %s | size: %d | ip: %s | server_port: %d\n", name, size, client_ip, port);
    pthread_mutex_lock(&mutex);
    if (write(pipe_fd[1], buffer, strlen(buffer)) < 0) {
        pthread_mutex_unlock(&mutex);
        free(buffer);
        return -1;
    }
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&condition);

Seems like on Ubuntu when I call pthread_cond_signal(&condition) it doesn't return errors but it also doesn't trigger the condition variable, so the process calling pthread_cond_wait(&condition, &mutex) never passes.

The stranger thing is that mutex is working good instead, pipe too.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Does the real code also lack all error checking? The `pthread_*()` functions return useful information. Error checking (and logging) is debugging for free. – alk Sep 06 '19 at 10:29

1 Answers1

2

Usage of condition variable is wrong.

It should be:

In consumer thread:

pthread_mutex_lock(&mutex);
pthread_cond_wait(&condition, &mutex); //Automatically unlocks the mutex and waits for signal.
pthread_mutex_unlock(&mutex);

In producer thread:

pthread_mutex_lock(&mutex);
pthread_cond_signal(&condition);
pthread_mutex_unlock(&mutex);

Since you mentioned in the comment that it's still not working, please try the below code.

   char buffer[8192];
    while(1) {
        bzero(buffer, sizeof buffer);
        pthread_mutex_lock(&mutex);
        while(!flag) {    //Share the flag between the process and initialize to zero. This is required to handle spurious signals.
            pthread_cond_wait(&condition, &mutex); //Automatically mutex will be unlocked. It will be locked again when signal is detected.
        }
        flag = 0; //Reset flag
        pthread_mutex_unlock(&mutex);
        read(pipe_fd[0], buffer, sizeof buffer);
        _log(buffer);
    }

And

char *buffer = malloc(SIZE);
sprintf(buffer, "name: %s | size: %d | ip: %s | server_port: %d\n", name, size, client_ip, port);
//pthread_mutex_lock(&mutex); //No need to lock here
if (write(pipe_fd[1], buffer, strlen(buffer)) < 0) {
    //pthread_mutex_unlock(&mutex);
    free(buffer);
    return -1;
}
pthread_mutex_lock(&mutex);
flag=1; //Update the flag.
pthread_cond_signal(&condition);
pthread_mutex_unlock(&mutex);
MayurK
  • 1,925
  • 14
  • 27
  • ok i didn't know it unlocks the mutex automatically. By the way, I tried this solution but nothing happened – Jacopo Rufini Sep 06 '19 at 09:35
  • It could be because of spurious signal. Please check this post: https://stackoverflow.com/a/13122435/6284997 – MayurK Sep 06 '19 at 09:45
  • Thank you, this solved partly my problem. It works now, but after first request, it stops handling the signal. I'll investigate more later, thank you again. – Jacopo Rufini Sep 06 '19 at 10:46