【发布时间】:2022-01-16 06:38:14
【问题描述】:
如果线程 ID 的生命周期在线程终止后结束,则如果它是使用设置为 PTHREAD_CREATE_DETACHED 的 detachstate 属性创建的,或者已为该线程调用了 pthread_detach() 或 pthread_join()。
在下面的程序中创建了一个线程。该线程执行thread_task() 例程。例程完成后,线程退出,但是,因为它的 detachstate 属性是 PTHREAD_CREATE_JOINABLE (默认),我希望在这个线程上调用 pthread_cancel() 是安全的并且不会返回任何错误。 由于大量的错误检查,它有点长
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int counter=0;
void free_buffer(void* buff)
{
printf("freeing buffer\n");
free(buff);
}
void* thread_task(void* arg)
{
void* buffer = malloc(1000);
pthread_cleanup_push(free_buffer, buffer);
for(int i = 0; i < 100000; i++) { // 'counter' is a global variable
for(counter = 0; counter < 10000; counter++);
pthread_testcancel();
}
pthread_cleanup_pop(1);
printf("Thread exiting\n");
return NULL;
}
int main()
{
pthread_t tid;
int errnum = pthread_create(&tid, NULL, thread_task, NULL);
if(errnum != 0) {
fprintf(stderr, "pthread_create(): %s\n", strerror(errnum));
exit(EXIT_FAILURE);
}
getchar();
errnum = pthread_cancel(tid);
if(errnum != 0) {
fprintf(stderr, "pthread_cancel(): %s [%d]\n", strerror(errnum), errnum);
exit(EXIT_FAILURE);
}
void* ret;
errnum = pthread_join(tid, &ret);
if(errnum != 0) {
fprintf(stderr, "pthread_join(): %s [%d]\n", strerror(errnum), errnum);
exit(EXIT_FAILURE);
}
if(ret == PTHREAD_CANCELED) {
printf("Thread was canceled\n");
}
printf("counter = %d\n", counter);
}
但这不会发生。当我运行程序时,我看到的消息是:
// wait for the thread routine to finish...
freeing buffer
Thread exiting
// press any key
pthread_cancel(): No such process [3]
这似乎表明线程退出后,它的 TID 不再有效。这不违反标准吗?这是怎么回事?
【问题讨论】:
-
FWIW:在添加四行
#include ...和int counter的全局声明后,我能够运行您的程序。它的行为方式与您描述的不同。我的环境:Apple clang 13.0.0,在基于 ARM 的 Mac 上,运行 macOS 11.6。无论取消调用是在线程到达thread_task()的末尾之前还是之后发生,我都没有看到任何错误消息。 你使用什么构建工具链?你在什么平台上运行它? -
我首先在 WSL Ubuntu 20.04(使用 GCC 9.3.0 编译)上运行它。我第二次在 Arch Linux 上运行它(使用 GCC 11.1.0 编译)。每次都得到相同的输出。
标签: c multithreading pthreads posix cancellation