0

I have to create a solution to the readers writers problem using posix pthreads, I have condensed my code down to pseudocode mixed with C to reduce the size of the code.

The writer thread finishes fine but the reader threads never terminate/exit so the Reader join is waiting forever, and the program hangs.

I believe it is related to the wait condition pthread_cond_wait(&qElement, &mutex); in the reader function. It may be waiting for a terminated writer thread to signal. I have tried encapsulating it with if(!finished) so it only waits if the writer is still active but that still hasn't worked.

I am not sure what to do and believe it as a logic error with my pthread handling.

Would really appreciate the help.

Global variables in header file : 

#define TRUE 1
#define FALSE 0

int finished = FALSE

pthread_cond_t qServiced = PTHREAD_COND_INITIALIZER;
pthread_cond_t qEmpty = PTHREAD_COND_INITIALIZER;
pthread_cond_t qElement = PTHREAD_COND_INITIALIZER;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int main()
{
    Create 1 writer thread
    Create 2 reader threads

    Writer join <- Success 
    Reader join <- Program hangs here


void* writer()
{
    int totalQueued = 0; 
    int tasks = 20; 

    while(!finished)
    {
        pthread_mutex_lock(&mutex); 

        while(isFull(q))
        {
            pthread_cond_wait(&qEmpty, &mutex); 
        }

        if(totalQueued < tasks)
        {
            for(j = 0; j < 2; j++) //Add 2 numbers at a time 
            {
                if(!(isFull(q)))
                {
                    //Assume random numbers added to queue 
                    totalQueued++;
                }
            }
            pthread_cond_signal(&qElement);
            pthread_cond_wait(&qServiced, &mutex);
        }
        else
        {
            finished = TRUE; 
        }
        pthread_mutex_unlock(&mutex); 
    } 

    //Thread exits
}

void* reader()
{
    while(!finished)
    {
        pthread_mutex_lock(&mutex);

        while(isEmpty(q)) //If the queue is empty 
        {
            pthread_cond_signal(&qEmpty);
            pthread_cond_wait(&qElement, &mutex);
        }

        int n = dequeue(q); 
        printf("%d\n", n); 

        pthread_cond_signal(&qServiced); //Signal that task has been serviced
        pthread_mutex_unlock(&mutex);
    }
}
Kevin
  • 43
  • 1
  • 7

1 Answers1

1

You having presented only a sketch of your code, I am unable to perform a complete analysis, but even the sketch shows a deficiency in your approach. When the writer makes new data available it unblocks one reader:

            pthread_cond_signal(&qElement);

If both readers are waiting when the writer posts the last pieces of work (which appears likely), then one will be left waiting when the writer terminates.

The best solutions revolve around using pthread_cond_broadcast() instead of or in addition to pthread_cond_signal(). It should be fine to just substitute the latter for the former, since your readers ought to be protecting themselves against spurious wakeups anyway (and it looks like they indeed are). If you prefer, though, you can have the writer broadcast just before it terminates, or have the main thread broadcast after it joins the writer.

Additionally, I'm inclined to think that you're using a lot more CVs than you actually need. Very likely you can use just one, which will be simpler both to write and to reason about.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • I apologize, I simply did not wish to paste all the code. I have done so here: https://pastebin.com/31NR4vT9 - I have attempted to replace signal with broadcast on line 93 but the issue still stands. – Kevin Apr 20 '19 at 13:46
  • 1
    @A1_, if the code presented in the question does not adequately convey the problem, and it sounds like it doesn't, then the thing to do is to reduce it to a [mcve] (or to construct an MCVE from scratch) that reproduces the issue, and to update your question to present that. We generally do not accept questions that rely on resources or code available only from external sites. – John Bollinger Apr 20 '19 at 15:31