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.

1
  • Does the real code also lack all error checking? The pthread_*() functions return useful information. Error checking (and logging) is debugging for free. Commented Sep 6, 2019 at 10:29

1 Answer 1

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);
Sign up to request clarification or add additional context in comments.

3 Comments

ok i didn't know it unlocks the mutex automatically. By the way, I tried this solution but nothing happened
It could be because of spurious signal. Please check this post: stackoverflow.com/a/13122435/6284997
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.

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.