Question: To create a program which takes user input but times out after some seconds (say it's 2 seconds for now).
Approach: I created two threads, one to wait for user input (inputThread with tid[0]) and other to sleep for 2 seconds (sleepThread with tid[1]). I cancel a thread from another thread's routine, as follows:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_t tid[2];
void* inputThread()
{
int n;
printf("Enter number:");
// wait for input; if input is given then go ahead and cancel the sleeper thread.
scanf("%d",&n);
// cancel the sleeper thread
pthread_cancel(tid[1]);
printf("Got value:%d\n",n);
}
void* sleepThread()
{
// sleep for 2 seconds and cancel the input thread.
sleep(2);
// cancel the input thread
pthread_cancel(tid[0]);
printf("\nNo value entered!\n");
}
int main(int argc, char const *argv[])
{
int r1,r2,r3,r4;
// input taking thread
r1 = pthread_create(&tid[0],NULL,inputThread,NULL);
// sleeping thread
r2 = pthread_create(&tid[1],NULL,sleepThread,NULL);
r3 = pthread_join(tid[0],NULL);
r4 = pthread_join(tid[1],NULL);
return 0;
}
As of now, the program works as expected.
But my friend says that it's not guaranteed to work since it depends on how threads are scheduled. He tried explaining the same to me but I couldn't understand. He also said that pthread_cancel is only a request to cancel the threads and it may not succeed.
So can someone please point out the potential mistake and best practice to avoid the same. Any changes to be made to guarantee the program's working is also appreciated.
Your friend is right about the part that pthread_cancel is a request to the cancel the thread and might not succeed always.
For the part about scheduling you need to provide what arguments he had.
For a solution to your problem, you can abandon using threads all together (unless that is a requirement for your assignment) and use select with read.
This will make the solution not-portable (only conforming to POSIX), but pthreads is also anyway not portable.
select allows you to wait on a file descriptor (in this case 0) for data to be available for a read. It also allows you to set a timeout.
fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
int ret = select(1, &set, NULL, NULL, &timeout);
if (ret == 1) {
char buffer[20];
int n;
read(0, buffer, 20);
sscanf(buffer, "%d", &n);
printf("Got value:%d\n",n);
} else {
printf("Time out\n");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With