3

I am learning the concept of pthread. I wrote a code for the following question :

Implement the following model: Create a master thread. It opens a file. At random intervals, the master thread creates worker threads at random intervals and each worker thread will sleep for random intervals before it reads a line from the file and finally exits.

I wrote the following code :

#include<stdio.h>
#include<pthread.h>

char c;

void *f1(void *f)
{
    printf("Calling from thread 1\n");
    sleep(rand()%2);
    while(c!='\n'&& c!=EOF)
    {
        printf("1 %c\n",c);
        c=getc(f);
    }
    pthread_exit(NULL);
}


void *f2(void *f)
{
    printf("Calling from thread 2\n");
    sleep(rand()%2);
    while(c!='\n' && c!=EOF)
    {
        printf("2 %c\n",c);
        c=getc(f);
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t tid1,tid2;
    FILE *f;
    f=fopen("new.txt","r");
    int i;
    c=getc(f);
    while(c!=EOF)
    {
        i=rand()%2;
        sleep(i);
        pthread_create(&tid1,NULL,f1,(void *)f);
        i=rand()%2;
        sleep(i);
        pthread_create(&tid2,NULL,f2,(void *)f);
    }
    pthread_exit(NULL);
    return 0;
}

While executing, the code enters an infinite loop. Sometimes only the first line is being executed then it enters an infinite loop. Even when I used pthread_join, the problem was not solved. Why is it entering an infinite loop?

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
  • 6
    `char c;` should be `int c;`. `EOF` does not fit in a `char`, so `c != EOF` will never be false. – Kninnug Aug 20 '15 at 10:05

4 Answers4

4

Here are some issues:

  • Your using one global variable c in main and both threads. So they are all overwriting the value used by the others.
  • You have an almost exact copy of the code run as thread: f1() and f2(). Instead you can have one function f() that you run by multiple threads. This is a main idea of multi-threading.
  • You can print the thread ID using pthread_self().
  • pthread_exit() is called implicitly when you return from a function.
  • main() was not started as a thread explicitly, so calling pthread_exit() does not make sense.
  • You're lacking communication & synchronisation between the threads, telling each other which line they'll be reading. You should use the 'master' thread to keep track, and let each 'worker' thread ask where to read. (This is a non-trivial assignment I'd say.)
Community
  • 1
  • 1
meaning-matters
  • 21,929
  • 10
  • 82
  • 142
2

EDIT AFTER @Maksim Solovjov COMMENT

Actually the issue is you are reading only a line is read i.e. till '\n' is hit. Once any of the thread reads this '\n' character, no other thread (or main while-loop) will read further. And thus it'll stuck in loop forever.

So, if you change the while loop in both the thread as below,

while(c!=EOF)

threads will go ahead and read next line. Finally the flow will reach EOF and thread can exit.

After modifying your threads code will look like

void *f1(void *f)
{
    printf("Calling from thread 1\n");
    sleep(rand()%2);
    while( c!=EOF)  //======>>>this is where change is required.
    {
        printf("1 %c\n",c);
        c=getc((FILE *)f);
    }
    pthread_exit(NULL);
}
Pawan
  • 1,537
  • 1
  • 15
  • 19
  • This would break the logic: only the worker threads are supposed to read the line from input judging from the assignment statement – Maksim Solovjov Aug 20 '15 at 10:34
  • @MaksimSolovjov I updated the answer based on your comment. The issue was largely the same, the `getc()` was not reaching till EOF :) – Pawan Aug 20 '15 at 11:10
  • But I am supposed to read 1 line from a single thread. By giving the condition (c!=EOF), I am reading the whole file from a single thread. –  Sep 01 '15 at 11:45
1

There are never "two threads in infinite loop". Its the main thread which is in inifinite loop. This is happening because: You are reading file in two different functions called by different threads till either of one reach EOF or "\n". Say your thread executing function one reaches "\n" it will quit. But now main thread will go in inifinite loop because EOF will never come as both function checking for while(c!='\n'&& c!=EOF) to further read file.

For coming out of this situation, you can use one global state variable, which will take care of "\n" blocking.

Code will be look like this:

#include<stdio.h>
#include<pthread.h>

char c;
int isBlock;

void *f1(void *f)
{
    printf("Calling from thread 1\n");
    sleep(rand()%2);
    while((c!='\n' || isBlock) && c!=EOF)
    {
        isBlock = 0;
        printf("1 %c\n",c);
        c=getc(f);
    }
    isBlock = 1;
    printf("exiting from thread 1\n");
    pthread_exit(NULL);
}


void *f2(void *f)
{
    printf("Calling from thread 2\n");
    sleep(rand()%2);
    while((c!='\n'|| isBlock) && c!=EOF)
    {
        isBlock = 0;
        printf("2 %c\n",c);
        c=getc(f);
    }
    isBlock = 1;
    printf("exiting from thread 2\n");
    pthread_exit(NULL);
}

int main()
{
    pthread_t tid1,tid2;
    FILE *f;
    f=fopen("checkConnection.cpp","r");
    int i;
    c=getc(f);
    isBlock = 0;
    while(c!=EOF)
    {
        //c=getc(f);
        i=rand()%2;
        sleep(i);
        pthread_create(&tid1,NULL,f1,(void *)f);
        i=rand()%2;
        sleep(i);
        pthread_create(&tid2,NULL,f2,(void *)f);
}
    pthread_exit(NULL);
    return 0;
}
linux user
  • 21
  • 4
1

In the 1st thread function f1, you are writing

while(c!='\n'&& c!=EOF)
    {
        printf("1 %c\n",c);
        c=getc(f);
    }

Then you get back to the main function and to the second thread. So right now, the value of c is '\n'. Thus in f2, you will not enter the loop. Hence, the while loop in main will continue forever since the value of c is not changing and is stuck in '\n'. This is reason for getting the infinite loop. So, you can also conclude that the threads that you created are not entering in any infinite loop.

Solution :

As soon as you exit the loop in the thread functions, change the value of c.

if(c!=EOF)
   c = getc(f);
Richa Tibrewal
  • 468
  • 7
  • 26