我目前正在学习C和POSIXAPI,特别是p线程.我遇到了以下情况,这让我很惊讶,似乎事情不应该是这样的.
线程内的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;
}
我预期该程序的输出如下:
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
但是,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
这似乎是不对的.取消请求不是信号,对吗?那为什么会导致sleep
中断呢?我预计代码会执行,就好像只有sleep(10)
个代码,而不是以下代码:
// before `thread`:
static pthread_mutex_t sleep_mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t sleep_cv = PTHREAD_COND_INITIALIZER;
static void *sleep_thread(void *arg)
{
int sleep_for = *((int *) arg);
sleep(sleep_for);
pthread_cond_broadcast(&sleep_cv);
return NULL;
}
static void *thread(void *arg)
{
// ...
// instead of `sleep`:
pthread_mutex_lock(&sleep_mut);
pthread_t sleep_thr;
int sleep_for = 10;
pthread_create(&sleep_thr, NULL, sleep_thread, &sleep_for);
pthread_cond_wait(&sleep_cv, &sleep_mut);
pthread_mutex_unlock(&sleep_mut);
// ...
}