问题
I am a beginner of multi-threaded programming, and now I know that when a signal was sent while waiting with pthead_cond_wait()
, the result depends on the OS.
Can somebody tell me how to know how the call was interrupted, and how to write portable code?
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
void
sigusr1_handler(int sig)
{
printf("signal called\n");
}
int
main()
{
int n;
pthread_mutex_t mut;
pthread_cond_t cond;
struct timespec ts;
signal(SIGUSR1, sigusr1_handler);
pthread_mutex_init(&mut, NULL);
pthread_cond_init(&cond, NULL);
pthread_mutex_lock(&mut);
printf("before cond_wait\n");
n = pthread_cond_wait(&cond, &mut);
printf("after pthread_cond_wait : %d\n", n);
perror("error pthread_cond_wait:");
pthread_mutex_unlock(&mut);
return 0;
}
MacOS X 10.11.4
cc -o condwait condwait.c -lpthread
Linux 2.6.32-642.3.1.el6.x86_64
gcc -o condwait condwait.c -lpthread
Solaris11 5.11 11.2
cc -D_POSIX_C_SOURCE -D_REENTRANT -mt -o condwait condwait.c -lpthread
MacOS X
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
after pthread_cond_wait : 0
error pthread_cond_wait:: Unknown error: 260
Solaris
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
after pthread_cond_wait : 0
error pthread_cond_wait : Error 0
Linux
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
$ jobs
[1]+ Running
When using Solaris native cond_wait()
, it returns EINTR
as documented.
Is there any idea how to know that pthread_cond_wait()
was interrupted?
回答1:
POSIX specifies that this function will never return EINTR. For portability to legacy OSes you can check for it anyway, it doesn't hurt
More importantly, you should be prepared for spurious wakeups. The function can return zero at any time for any reason wiith the condition not being met. The mutex will be locked. You have to check the condition and, if not met, go back to pthread_cond_wait.
回答2:
I read the Linux pthread_cond_wait
's man manual, it says:
If a signal is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread resumes waiting for the condition variable as if it was not interrupted, or it shall return zero due to spurious wakeup.
I guess other OS's also have manuals to help you figure it out.
回答3:
Thank you very much for everyone. Now I know that with using signal to stop long waiting condition do not work. pthread_cond_wait() resume waiting for the condition as if it was not interrupted, or it returns zero due to spurious wakeup. Then I want to do that, I will need a second lock like
pthread_mutex_lock(&mut);
while(condition_is_false) {
n = pthread_cond_timedwait();
if (n == ETIMEDOUT) {
pthread_mutex_lock(&mut2);
if (condition2_is_true) {
pthread_mutex_unlock(&mut2);
pthread_mutex_unlock(&mut);
return STOPPED;
}
pthread_mutex_unlock(&mut2);
}
}
pthread_mutex_unlock(&mut);
return 0;
Regards,
来源:https://stackoverflow.com/questions/39242148/pthread-cond-wait-and-signal-the-result-depend-on-os