如果进程在等待 pthread_cond_wait 时收到信号,在 Linux(和 MacOS)上会发生什么?

问题描述 投票:0回答:1

在Linux手册中,signal(7)手册页的“描述”的最后一部分,(https://man7.org/linux/man-pages/man7/signal.7.html)它说被信号中断的对 pthread_cond_wait 的调用将失败并返回 EINTR(除非在处理程序中设置了 sa_restart)

再次在Linux手册中,在pthread_cond_wait(3) (https://man7.org/linux/man-pages/man3/pthread_cond_wait.3p.html)页面中它说:

这些函数不应返回错误代码 [EINTR]。

这两页不是矛盾吗?

在我的 Mac 上,使用命令行手册我什至找不到页面 signal(7),并且 pthread_cond_wait(2) 页面没有有关 EINTR 失败的信息。

我在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){
}

输出为:

res = 0
errno = 260
Ended

我不知道这个输出意味着什么。 我认为260甚至超出了系统错误的范围。

那么这在 Linux 和 MacOS 中实际上是如何工作的呢?

c linux macos pthreads signals
1个回答
0
投票

这两页不是矛盾吗?

差不多,但请参阅下文。

根据经验,您应该选择更具体的来源而不是更笼统的来源。在这种情况下,这意味着依赖

pthread_cond_wait()
的手册页来获取有关该函数行为的信息。此外,我注意到您链接的
pthread_cond_wait
手册页回响了 该函数的 POSIX 规范,并且这两个来源也说:

如果将信号传递到等待条件变量的线程,则从信号处理程序返回后,线程将恢复等待条件变量,就好像它没有被中断一样,否则它将由于虚假唤醒而返回零。

您报告:

我在 MacOS 上使用以下代码进行了测试 [...]

输出为:

res = 0
errno = 260
Ended

我不知道这个输出意味着什么。

这意味着当被信号中断时,您的

pthread_cond_wait()
执行了执行虚假唤醒的选项,返回 0。这本身不是错误。

我认为260甚至超出了系统错误的范围。

数字 260 与定义的系统错误编号范围的关系是完全不相关的。
errno

的值仅在函数调用返回失败代码后立即传达有用信息,并且仅适用于记录为在错误时设置

errno
的函数。
pthread_cond_wait
不是这些函数之一 - 相反,它是返回值
is
错误号的函数之一。

那么这在 Linux 和 MacOS 中实际上是如何工作的呢?

您应该解释 Linux signal(7) 手册页以表明
在 Linux

上,被信号中断后,如果使用 pthread_cond_wait() 标志注册了处理程序,则

SA_RESTART
将自动重新启动,否则它将自动重新启动。返回给它的调用者。如果您愿意,您可以将“因错误
EINTR
失败”与
pthread_cond_signal()
的记录行为进行协调,将前者视为抽象规范,在
pthread_cond_wait()
的异常情况下实现为返回 0。或者你可以在这个细节中将 signal(7) 算作错误。
对于 MacOS,您自己的实验表明 

pthread_cond_wait()

在被信号中断后返回 0。其他情况下,该功能可能会自动重启。

    

© www.soinside.com 2019 - 2024. All rights reserved.