In the Linux manual, in the signal(7) manual page, last section of "description", (https://man7.org/linux/man-pages/man7/signal.7.html) it says that a call to pthread_cond_wait interrupted by a signal will fail with EINTR (unless sa_restart was set in the handler)
Again in the linux manual, in the pthread_cond_wait(3) (https://man7.org/linux/man-pages/man3/pthread_cond_wait.3p.html) page it says:
These functions shall not return an error code of [EINTR].
Aren't those two pages contradictory?
On my Mac, using the command line manual I can't even find the page signal(7), and the pthread_cond_wait(2) page has no info about failing with EINTR.
I did a test with the following code on MacOS:
int main(){
struct sigaction siga;
memset(&siga, 0, sizeof(siga));
siga.sa_handler = handle;
sigaction(SIGINT, &siga, NULL);
pthread_t thread;
pthread_create(&thread, 0, task, NULL);
sleep(2);
pthread_kill(thread, SIGINT);
pthread_join(thread, NULL);
printf("Ended\n");
return 0;
}
void *task(void * arg){
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_mutex_lock(&mutex);
errno = 0;
int res = pthread_cond_wait(&cond, &mutex);
printf("res = %d\n", res);
printf("errno = %d\n", errno);
return 0;
}
void handle(int arg){
}
The output is:
res = 0
errno = 260
Ended
I have no idea what this output means. I think 260 is even outside the range of system errors.
So how does this actually works in Linux and MacOS?
Aren't those two pages contradictory?
Pretty much, but see below.
As a rule of thumb, you should go with the more specific source over the more general one. In this case, that means relying on the pthread_cond_wait()
's manual page for information about the behavior of that function. Furthermore, I note that the pthread_cond_wait
manual page you linked echoes the POSIX specifications for that function, and both of those sources also say:
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.
You report:
I did a test with the following code on MacOS [...]
The output is:
res = 0 errno = 260 Ended
I have no idea what this output means.
It means that when interrupted by a signal, your pthread_cond_wait()
exercised the option of performing a spurious wakeup, returning 0. This is not an error per se.
I think 260 is even outside the range of system errors.
It is absolutely irrelevant how the number 260 relates to the range of defined system error numbers. The value of errno
conveys useful information only in the immediate wake of a function call returning a failure code, and then only for those functions that are documented to set errno
on error. pthread_cond_wait
is not one of those functions -- instead, it is among those whose return value is the error number.
So how does this actually works in Linux and MacOS?
You should interpret the Linux signal(7) manual page to indicate that on Linux, after being interrupted by a signal, pthread_cond_wait()
will be automatically restarted if the handler was registered with the SA_RESTART
flag, and otherwise it will return to its caller. If you like, you can reconcile "fails with the error EINTR
" with the documented behavior of pthread_cond_signal()
by taking the former to be an abstract specification, realized as returning 0 in the unusual case of pthread_cond_wait()
. Or you can just count signal(7) as wrong in this detail.
As for MacOS, your own experiment has shown pthread_cond_wait()
returning 0 after being interrupted by a signal. Under other circumstances, the function might be automatically restarted instead.