I have a main thread which create child threads to do various task. There is a child thread which is tasked to report on the status every 100s
My current mechanism of stopping the thread is to observe a global boolean. Somewhat like this
Child thread
void* ReportThread(bool* operation)
{
while(*operation)
{
// do its reporting task
// ........
int counter = 0;
while( counter < 100 && operation )
{
// let it sleep for 1 seconds and wake up to check
sleep(1);
sleepCounter = 1;
}
}
}
Parent (Main) Thread:
bool operation = false;
int main(){
pthread_t tid;
err = pthread_create(&tid), NULL, &ReportThread, &operation);
printf("Please input esc to end operation \n");
while ((ch = getchar()) != 27);
operation =true;
pthread_join(tid,NULL);
return 0;
}
The problem:
- It seem that using sleep(n). The number of seconds seem very inconsistent. When the program is stopped, this thread takes a while maybe 10 second to actually stop
- Is there a way to interrupt a thread to sleep? I heard you could use signal. I am coding in linux
- Can I just simply just use a pthread_cancel(tid) instead of pthread_join(tid)?
Regards
CodePudding user response:
This part
while( counter < 100 || operation )
{
// let it sleep for 1 seconds and wake up to check
sleep(1);
sleepCounter = 1;
}
is wrong.
First I assume that sleepCounter = 1;
is really a typo and that it should be:
while( counter < 100 || operation )
{
// let it sleep for 1 seconds and wake up to check
sleep(1);
counter = 1;
}
Then the problem is that even if operation
is set to false by some other thread, the while
will not finish until counter
reach 100.
The code should be
while( counter < 100 && operation )
{
// let it sleep for 1 seconds and wake up to check
sleep(1);
counter = 1;
}
Further, in main
you never set operation
to false. Another typo?
CodePudding user response:
You don't need two while
loops. And if you want to set a timer, use time functions for it, because sleep
is a cancellation point and it is not guaranteed that sleep
actually sleeps that amount of time.
Example:
void* ReportThread(void *args)
{
time_t start = time(NULL);
time_t now;
bool *operation = (bool*) args;
while (*operation) { //while active
now = time(NULL); //get current time
if (now - start >= 100) { //if the threshold is exceeded
start = now; //reset timer
//and probably do other stuff
}
sleep(1); //sleep for one second
}
return NULL;
}
The example above has a max lag of one second, that means if you set operation
to false
right at that moment when the thread entered the sleep state, you have to wait until sleep
returns, only then it will recognize the modified state. The example also has the advantage, that you can easily modify the threshold value (since it depends on the 'real' time, instead of a counter and a non accurate sleep time).
Btw. the variable operation
should be either an atomic boolean or protected by a mutex (since it is accessed from different threads).
To answer the questions of your problem:
- should be answered by the example above
- since i mentioned it before,
sleep
is a cancellation point, that means it gets interrupted if the process handles a signal (see man pthreads - section Cancellation points). - see man pthread_cancel - section Notes
On Linux, cancellation is implemented using signals. Under the NPTL threading implementation, the first real-time signal (i.e., signal 32) is used for this purpose. On LinuxThreads, the second real-time signal is used, if real-time signals are available, otherwise SIGUSR2 is used.
You cannot use pthread_cancel
over pthread_join
! You have to use pthread_join
in either case (described in detail in the man page).
CodePudding user response:
I don't know if this will fix all your problems, but it's a bit too much for a comment. One problem, your ReportThread
function signature is wrong. It should be:
void* ReportThread(void* args);
And then in that function you need to do something like:
void* ReportThread(void* args)
{
bool* operation = (bool*)args;
while(*operation)
{
...
}
}
I'm not sure how it's working right now, but your compiler should at least be issuing a warning trying to convert a bool*
type to a bool
.
Also be aware of race conditions on operation