C pthreads - 尽管取消状态已禁用,但为什么“睡眠”会被线程取消请求中断?

fel*_*321 5 c multithreading pthreads

我目前正在学习 C 和 POSIX API,特别是 pthreads。我遇到了以下情况,这让我感到惊讶,似乎不应该是这样。尽管取消状态在该线程中设置为禁用,但线程内的调用sleep仍被主线程的取消请求中断。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>

static void *thread(void *arg)
{
    int oldstate;

    printf("other thread: started\n");

    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
    printf("other thread: started doing thing that can't be canceled\n");

    errno = 0;
    sleep(10);
    if (errno)
        perror("sleep");

    printf("other thread: finished doing thing that can't be canceled\n");
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);

    printf("other thread: exiting\n");

    return NULL;
}

int main(void)
{
    pthread_t thr;
    void *res;

    pthread_create(&thr, NULL, thread, NULL);
    printf("main: created other thread\n");

    printf("main: letting other thread work for 3 seconds...\n");
    sleep(3);
    printf("main: canceling other thread\n");
    pthread_cancel(thr);

    printf("main: joining with other thread\n");
    res = NULL;
    pthread_join(thr, &res);
    if (res == PTHREAD_CANCELED)
        printf("main: canceled other thread\n");
    else
        printf("main: other thread result: %p\n", res);

    printf("main: exiting\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我期望该程序的输出如下:

main: created other thread
main: letting other thread work for 3 seconds...
other thread: started
other thread: started doing thing that can't be canceled
main: canceling other thread
main: joining with other thread
other thread: finished doing thing that can't be canceled
other thread: exiting
main: canceled other thread
main: exiting
Run Code Online (Sandbox Code Playgroud)

然而,sleep被中断,输出如下:

main: created other thread
main: letting other thread work for 3 seconds...
other thread: started
other thread: started doing thing that can't be canceled
main: canceling other thread
main: joining with other thread
sleep: Interrupted system call
other thread: finished doing thing that can't be canceled
other thread: exiting
main: canceled other thread
main: exiting
Run Code Online (Sandbox Code Playgroud)

这似乎是错误的。取消请求不是一个信号,对吗?那么为什么会导致sleep中断呢?我希望代码能够像sleep(10)下面的代码一样执行:

main: created other thread
main: letting other thread work for 3 seconds...
other thread: started
other thread: started doing thing that can't be canceled
main: canceling other thread
main: joining with other thread
other thread: finished doing thing that can't be canceled
other thread: exiting
main: canceled other thread
main: exiting
Run Code Online (Sandbox Code Playgroud)

fel*_*321 0

正如我在评论中指出的那样,Linux 实际上确实使用信号实现了取消。这就解释了一切。